home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_13_08 / phillip2 / cips7.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-20  |  120.0 KB  |  4,413 lines

  1.  
  2.    /*************************** 
  3.    * 
  4.    *   cips7.c 
  5.    *   COMPOSITE FILE COMPRISING: 
  6.    *   ed.c 
  7.    *   skeleton.c 
  8.    *   segment.c 
  9.    *   segment2.c 
  10.    * 
  11.    ***************************\ 
  12.  
  13.  
  14.  
  15.        /**********************************************
  16.        *
  17.        *   file d:\cips\ed.c
  18.        *
  19.        *   Functions: This file contains
  20.        *      erosion
  21.        *      dilation
  22.        *      mask_erosion
  23.        *      mask_dilation
  24.        *      interior_outline
  25.        *      exterior_outline
  26.        *      copy_3_x_3
  27.        *      opening
  28.        *      closing
  29.        *      get_shape_options
  30.        *
  31.        *   Purpose:
  32.        *      These functions perform the erosion,
  33.        *      dilation, outlining, opening and
  34.        *      closing operations.
  35.        *
  36.        *   External Calls:
  37.        *      wtiff.c - round_off_image_size
  38.        *                create_file_if_needed
  39.        *                write_array_into_tiff_image
  40.        *      tiff.c - read_tiff_header
  41.        *      rtiff.c - read_tiff_image
  42.        *      numcvrt.c - get_integer
  43.        *
  44.        *   Modifications:
  45.        *      14 March 1993 - created
  46.        *
  47.        ************************************************/
  48.  
  49. #include "cips.h"
  50.  
  51.  
  52.  
  53. short edmask1[3][3] = {{0, 1, 0},
  54.                        {0, 1, 0},
  55.                        {0, 1, 0}};
  56.  
  57. short edmask2[3][3] = {{0, 0, 0},
  58.                        {1, 1, 1},
  59.                        {0, 0, 0}};
  60.  
  61. short edmask3[3][3] = {{0, 1, 0},
  62.                        {1, 1, 1},
  63.                        {0, 1, 0}};
  64.  
  65. short edmask4[3][3] = {{1, 1, 1},
  66.                        {1, 1, 1},
  67.                        {1, 1, 1}};
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74.      /*******************************************
  75.      *
  76.      *   mask_dilation(...
  77.      *
  78.      *   This function performs the dilation
  79.      *   operation using the erosion-dilation
  80.      *   3x3 masks given above.  It works on
  81.      *   0-value images.
  82.      *
  83.      *******************************************/
  84.  
  85. mask_dilation(in_name, out_name, the_image, out_image,
  86.               il, ie, ll, le, value, mask_type)
  87.    char   in_name[], out_name[];
  88.    int    il, ie, ll, le;
  89.    short  the_image[ROWS][COLS],
  90.           out_image[ROWS][COLS],
  91.           mask_type, value;
  92. {
  93.    int    a, b, count, i, j, k;
  94.    short  mask[3][3], max;
  95.  
  96.       /**************************************
  97.       *
  98.       *   Copy the 3x3 erosion-dilation mask
  99.       *   specified by the mask_type.
  100.       *
  101.       ***************************************/
  102.  
  103.    switch(mask_type){
  104.       case 1:
  105.          copy_3_x_3(mask, edmask1);
  106.          break;
  107.       case 2:
  108.          copy_3_x_3(mask, edmask2);
  109.          break;
  110.       case 3:
  111.          copy_3_x_3(mask, edmask3);
  112.          break;
  113.       case 4:
  114.          copy_3_x_3(mask, edmask4);
  115.          break;
  116.       default:
  117.          printf("\nInvalid mask type, using mask 4");
  118.          copy_3_x_3(mask, edmask4);
  119.          break;
  120.    }
  121.  
  122.    create_file_if_needed(in_name, out_name, out_image);
  123.  
  124.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  125.  
  126.       /***************************
  127.       *
  128.       *   Loop over image array
  129.       *
  130.       ****************************/
  131.  
  132.    printf("\n");
  133.  
  134.    for(i=1; i<ROWS-1; i++){
  135.       if( (i%10) == 0) printf("%3d", i);
  136.       for(j=1; j<COLS-1; j++){
  137.          max = 0;
  138.          for(a=-1; a<=1; a++){
  139.              for(b=-1; b<=1; b++){
  140.                 if(mask[a+1][b+1] == 1){
  141.                    if(the_image[i+a][j+b] > max)
  142.                       max = the_image[i+a][j+b];
  143.                 }  /* ends if mask == 1 */
  144.              }  /*  ends loop over b */
  145.          }  /* ends loop over a */
  146.          out_image[i][j] = max;
  147.       }  /* ends loop over j */
  148.    }  /* ends loop over i */
  149.  
  150.    fix_edges(out_image, 3);
  151.  
  152.    write_array_into_tiff_image(out_name, out_image,
  153.                                il, ie, ll, le);
  154.  
  155. }  /* ends mask_dilation */
  156.  
  157.  
  158.  
  159.  
  160.  
  161.      /*******************************************
  162.      *
  163.      *   mask_erosion(...
  164.      *
  165.      *   This function performs the erosion
  166.      *   operation using the erosion-dilation
  167.      *   3x3 masks given above.  It works on
  168.      *   0-value images.
  169.      *
  170.      *******************************************/
  171.  
  172. mask_erosion(in_name, out_name, the_image, out_image,
  173.              il, ie, ll, le, value, mask_type)
  174.    char   in_name[], out_name[];
  175.    int    il, ie, ll, le;
  176.    short  the_image[ROWS][COLS],
  177.           out_image[ROWS][COLS],
  178.           mask_type, value;
  179. {
  180.    int    a, b, count, i, j, k;
  181.    short  mask[3][3], min;
  182.  
  183.       /**************************************
  184.       *
  185.       *   Copy the 3x3 erosion-dilation mask
  186.       *   specified by the mask_type.
  187.       *
  188.       ***************************************/
  189.  
  190.    switch(mask_type){
  191.       case 1:
  192.          copy_3_x_3(mask, edmask1);
  193.          break;
  194.       case 2:
  195.          copy_3_x_3(mask, edmask2);
  196.          break;
  197.       case 3:
  198.          copy_3_x_3(mask, edmask3);
  199.          break;
  200.       case 4:
  201.          copy_3_x_3(mask, edmask4);
  202.          break;
  203.       default:
  204.          printf("\nInvalid mask type, using mask 4");
  205.          copy_3_x_3(mask, edmask4);
  206.          break;
  207.    }
  208.  
  209.    create_file_if_needed(in_name, out_name, out_image);
  210.  
  211.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  212.  
  213.       /***************************
  214.       *
  215.       *   Loop over image array
  216.       *
  217.       ****************************/
  218.  
  219.    printf("\n");
  220.  
  221.    for(i=1; i<ROWS-1; i++){
  222.       if( (i%10) == 0) printf("%3d", i);
  223.       for(j=1; j<COLS-1; j++){
  224.          min = value;
  225.          for(a=-1; a<=1; a++){
  226.              for(b=-1; b<=1; b++){
  227.                 if(mask[a+1][b+1] == 1){
  228.                    if(the_image[i+a][j+b] < min)
  229.                       min = the_image[i+a][j+b];
  230.                 }  /* ends if mask == 1 */
  231.              }  /*  ends loop over b */
  232.          }  /* ends loop over a */
  233.          out_image[i][j] = min;
  234.       }  /* ends loop over j */
  235.    }  /* ends loop over i */
  236.  
  237.    fix_edges(out_image, 3);
  238.  
  239.    write_array_into_tiff_image(out_name, out_image,
  240.                                il, ie, ll, le);
  241.  
  242. }  /* ends mask_erosion */
  243.  
  244.  
  245.  
  246.  
  247.  
  248.      /*******************************************
  249.      *
  250.      *   erosion(...
  251.      *
  252.      *   This function performs the erosion
  253.      *   operation.  If a value pixel has more
  254.      *   than the threshold number of 0
  255.      *   neighbors, you erode it by setting it
  256.      *   to 0.
  257.      *
  258.      *******************************************/
  259.  
  260. erosion(in_name, out_name, the_image, out_image,
  261.         il, ie, ll, le, value, threshold)
  262.    char   in_name[], out_name[];
  263.    int    il, ie, ll, le;
  264.    short  the_image[ROWS][COLS],
  265.           out_image[ROWS][COLS],
  266.           threshold, value;
  267. {
  268.    int    a, b, count, i, j, k;
  269.  
  270.    create_file_if_needed(in_name, out_name, out_image);
  271.  
  272.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  273.  
  274.       /***************************
  275.       *
  276.       *   Loop over image array
  277.       *
  278.       ****************************/
  279.  
  280.    for(i=0; i<ROWS; i++)
  281.       for(j=0; j<COLS; j++)
  282.          out_image[i][j] = the_image[i][j];
  283.  
  284.    printf("\n");
  285.  
  286.    for(i=1; i<ROWS-1; i++){
  287.       if( (i%10) == 0) printf("%3d", i);
  288.       for(j=1; j<COLS-1; j++){
  289.          if(the_image[i][j] == value){
  290.             count = 0;
  291.             for(a=-1; a<=1; a++){
  292.                 for(b=-1; b<=1; b++){
  293.                       if(the_image[i+a][j+b] == 0)
  294.                          count++;
  295.                 }  /*  ends loop over b */
  296.             }  /* ends loop over a */
  297.             if(count > threshold) out_image[i][j] = 0;
  298.          }  /* ends if the_image == value */
  299.       }  /* ends loop over j */
  300.    }  /* ends loop over i */
  301.  
  302.    fix_edges(out_image, 3);
  303.  
  304.    write_array_into_tiff_image(out_name, out_image,
  305.                                il, ie, ll, le);
  306.  
  307. }  /* ends erosion */
  308.  
  309.  
  310.  
  311.  
  312.  
  313.      /*******************************************
  314.      *
  315.      *   dilation(...
  316.      *
  317.      *   This function performs the dilation
  318.      *   operation.  If a 0 pixel has more than
  319.      *   threshold number of value neighbors,
  320.      *   you dilate it by setting it to value.
  321.      *
  322.      *******************************************/
  323.  
  324. dilation(in_name, out_name, the_image, out_image,
  325.          il, ie, ll, le, value, threshold)
  326.    char   in_name[], out_name[];
  327.    int    il, ie, ll, le;
  328.    short  the_image[ROWS][COLS],
  329.           out_image[ROWS][COLS],
  330.           threshold, value;
  331. {
  332.    int    a, b, count, i, j, k;
  333.  
  334.    create_file_if_needed(in_name, out_name, out_image);
  335.  
  336.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  337.  
  338.       /***************************
  339.       *
  340.       *   Loop over image array
  341.       *
  342.       ****************************/
  343.  
  344.    printf("\n");
  345.  
  346.    for(i=1; i<ROWS-1; i++){
  347.       if( (i%10) == 0) printf("%3d", i);
  348.       for(j=1; j<COLS-1; j++){
  349.          out_image[i][j] = the_image[i][j];
  350.          if(the_image[i][j] == 0){
  351.             count = 0;
  352.             for(a=-1; a<=1; a++){
  353.                 for(b=-1; b<=1; b++){
  354.                    if(a!=0  &&  b!=0){
  355.                       if(the_image[i+a][j+b] == value)
  356.                          count++;
  357.                    }  /* ends avoid the center pixel */
  358.                 }  /*  ends loop over b */
  359.             }  /* ends loop over a */
  360.             if(count > threshold)
  361.                out_image[i][j] = value;
  362.          }  /* ends if the_image == 0 */
  363.       }  /* ends loop over j */
  364.    }  /* ends loop over i */
  365.  
  366.    fix_edges(out_image, 3);
  367.  
  368.    write_array_into_tiff_image(out_name, out_image,
  369.                                il, ie, ll, le);
  370.  
  371. }  /* ends dilation */
  372.  
  373.  
  374.  
  375.  
  376.  
  377.      /*******************************************
  378.      *
  379.      *   interior_outline(...
  380.      *
  381.      *   This function produces the outline of
  382.      *   any "holes" inside an object.  The
  383.      *   method is:
  384.      *      output = erosion of input
  385.      *      final output = input - output
  386.      *
  387.      *******************************************/
  388.  
  389. interior_outline(in_name, out_name, the_image,
  390.                  out_image, il, ie, ll, le, value,
  391.                  mask_type)
  392.    char   in_name[], out_name[];
  393.    int    il, ie, ll, le;
  394.    short  the_image[ROWS][COLS],
  395.           out_image[ROWS][COLS],
  396.           mask_type, value;
  397. {
  398.    int    a, b, count, i, j, k;
  399.    short  mask[3][3], max;
  400.  
  401.       /**************************************
  402.       *
  403.       *   Copy the 3x3 erosion-dilation mask
  404.       *   specified by the mask_type.
  405.       *
  406.       ***************************************/
  407.  
  408.    switch(mask_type){
  409.       case 1:
  410.          copy_3_x_3(mask, edmask1);
  411.          break;
  412.       case 2:
  413.          copy_3_x_3(mask, edmask2);
  414.          break;
  415.       case 3:
  416.          copy_3_x_3(mask, edmask3);
  417.          break;
  418.       case 4:
  419.          copy_3_x_3(mask, edmask4);
  420.          break;
  421.       default:
  422.          printf("\nInvalid mask type, using mask 4");
  423.          copy_3_x_3(mask, edmask4);
  424.          break;
  425.    }
  426.  
  427.    create_file_if_needed(in_name, out_name, out_image);
  428.  
  429.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  430.  
  431.    mask_erosion(in_name, out_name, the_image,
  432.                 out_image, il, ie, ll, le,
  433.                 value, mask_type);
  434.  
  435.    for(i=0; i<ROWS; i++)
  436.       for(j=0; j<COLS; j++)
  437.          the_image[i][j] =
  438.             the_image[i][j] - out_image[i][j];
  439.  
  440.    write_array_into_tiff_image(out_name, the_image,
  441.                                il, ie, ll, le);
  442.  
  443. }  /* ends interior_outline */
  444.  
  445.  
  446.  
  447.  
  448.  
  449.      /*******************************************
  450.      *
  451.      *   exterior_outline(...
  452.      *
  453.      *   This function produces the outline of
  454.      *   exterior of an object.  The
  455.      *   method is:
  456.      *      output = dilation of input
  457.      *      final output = output - input
  458.      *
  459.      *******************************************/
  460.  
  461.  
  462. exterior_outline(in_name, out_name, the_image, out_image,
  463.           il, ie, ll, le, value, mask_type)
  464.    char   in_name[], out_name[];
  465.    int    il, ie, ll, le;
  466.    short  the_image[ROWS][COLS],
  467.           out_image[ROWS][COLS],
  468.           mask_type, value;
  469. {
  470.    int    a, b, count, i, j, k;
  471.    short  mask[3][3], max;
  472.  
  473.       /**************************************
  474.       *
  475.       *   Copy the 3x3 erosion-dilation mask
  476.       *   specified by the mask_type.
  477.       *
  478.       ***************************************/
  479.  
  480.    switch(mask_type){
  481.       case 1:
  482.          copy_3_x_3(mask, edmask1);
  483.          break;
  484.       case 2:
  485.          copy_3_x_3(mask, edmask2);
  486.          break;
  487.       case 3:
  488.          copy_3_x_3(mask, edmask3);
  489.          break;
  490.       case 4:
  491.          copy_3_x_3(mask, edmask4);
  492.          break;
  493.       default:
  494.          printf("\nInvalid mask type, using mask 4");
  495.          copy_3_x_3(mask, edmask4);
  496.          break;
  497.    }
  498.  
  499.    create_file_if_needed(in_name, out_name, out_image);
  500.  
  501.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  502.  
  503.    mask_dilation(in_name, out_name, the_image,
  504.                  out_image, il, ie, ll, le,
  505.                  value, mask_type);
  506.  
  507.    for(i=0; i<ROWS; i++)
  508.       for(j=0; j<COLS; j++)
  509.          the_image[i][j] =
  510.             out_image[i][j] - the_image[i][j];
  511.  
  512.    write_array_into_tiff_image(out_name, the_image,
  513.                                il, ie, ll, le);
  514.  
  515. }  /* ends exterior_outline */
  516.  
  517.  
  518.      /***********************************************
  519.      *
  520.      *   copy_3_x_3(a, b)
  521.      *
  522.      *   This function copies a 3x3 array of shorts
  523.      *   from one array to another.  It copies array
  524.      *   b into array a.
  525.      *
  526.      ***********************************************/
  527.  
  528. copy_3_x_3(a, b)
  529.    short a[3][3], b[3][3];
  530. {
  531.    int i, j;
  532.    for(i=0; i<3; i++)
  533.       for(j=0; j<3; j++)
  534.          a[i][j] = b[i][j];
  535. }  /* ends copy_3_x_3 */
  536.  
  537.  
  538.  
  539.  
  540.  
  541.      /*******************************************
  542.      *
  543.      *   opening(...
  544.      *
  545.      *   Opening is erosion followed by dilation.
  546.      *   This routine will use the mask erosion
  547.      *   and dilation.  You could use the other
  548.      *   types and you could mix the two types.
  549.      *
  550.      *   The number parameter specifies how
  551.      *   erosions to perform before doing one
  552.      *   dilation.
  553.      *
  554.      *******************************************/
  555.  
  556. opening(in_name, out_name, the_image, out_image,
  557.         il, ie, ll, le, value, mask_type, number)
  558.    char   in_name[], out_name[];
  559.    int    il, ie, ll, le, number;
  560.    short  the_image[ROWS][COLS],
  561.           out_image[ROWS][COLS],
  562.           mask_type, value;
  563. {
  564.    int    a, b, count, i, j, k;
  565.    short  mask[3][3], max;
  566.  
  567.       /**************************************
  568.       *
  569.       *   Copy the 3x3 erosion-dilation mask
  570.       *   specified by the mask_type.
  571.       *
  572.       ***************************************/
  573.  
  574.    switch(mask_type){
  575.       case 1:
  576.          copy_3_x_3(mask, edmask1);
  577.          break;
  578.       case 2:
  579.          copy_3_x_3(mask, edmask2);
  580.          break;
  581.       case 3:
  582.          copy_3_x_3(mask, edmask3);
  583.          break;
  584.       case 4:
  585.          copy_3_x_3(mask, edmask4);
  586.          break;
  587.       default:
  588.          printf("\nInvalid mask type, using mask 4");
  589.          copy_3_x_3(mask, edmask4);
  590.          break;
  591.    }
  592.  
  593.    create_file_if_needed(in_name, out_name, out_image);
  594.  
  595.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  596.  
  597.    mask_erosion(in_name, out_name, the_image,
  598.                 out_image, il, ie, ll, le,
  599.                 value, mask_type);
  600.  
  601.    if(number > 1){
  602.       count = 1;
  603.       while(count < number){
  604.          count++;
  605.          mask_erosion(out_name, out_name, the_image,
  606.                        out_image, il, ie, ll, le,
  607.                        value, mask_type);
  608.       }  /* ends while */
  609.    }  /* ends if number > 1 */
  610.  
  611.    mask_dilation(out_name, out_name, the_image,
  612.                  out_image, il, ie, ll, le,
  613.                  value, mask_type);
  614.  
  615.    write_array_into_tiff_image(out_name, out_image,
  616.                                il, ie, ll, le);
  617.  
  618. }  /* ends opening */
  619.  
  620.  
  621.  
  622.  
  623.  
  624.      /*******************************************
  625.      *
  626.      *   closing(...
  627.      *
  628.      *   Closing is dilation followed by erosion.
  629.      *   This routine will use the mask erosion
  630.      *   and dilation.  You could use the other
  631.      *   types and you could mix the two types.
  632.      *
  633.      *   The number parameter specifies how
  634.      *   dilations to perform before doing one
  635.      *   erosion.
  636.      *
  637.      *******************************************/
  638.  
  639. closing(in_name, out_name, the_image, out_image,
  640.         il, ie, ll, le, value, mask_type, number)
  641.    char   in_name[], out_name[];
  642.    int    il, ie, ll, le, number;
  643.    short  the_image[ROWS][COLS],
  644.           out_image[ROWS][COLS],
  645.           mask_type, value;
  646. {
  647.    int    a, b, count, i, j, k;
  648.    short  mask[3][3], max;
  649.  
  650.       /**************************************
  651.       *
  652.       *   Copy the 3x3 erosion-dilation mask
  653.       *   specified by the mask_type.
  654.       *
  655.       ***************************************/
  656.  
  657.    switch(mask_type){
  658.       case 1:
  659.          copy_3_x_3(mask, edmask1);
  660.          break;
  661.       case 2:
  662.          copy_3_x_3(mask, edmask2);
  663.          break;
  664.       case 3:
  665.          copy_3_x_3(mask, edmask3);
  666.          break;
  667.       case 4:
  668.          copy_3_x_3(mask, edmask4);
  669.          break;
  670.       default:
  671.          printf("\nInvalid mask type, using mask 4");
  672.          copy_3_x_3(mask, edmask4);
  673.          break;
  674.    }
  675.  
  676.    create_file_if_needed(in_name, out_name, out_image);
  677.  
  678.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  679.  
  680.    mask_dilation(in_name, out_name, the_image,
  681.                  out_image, il, ie, ll, le,
  682.                  value, mask_type);
  683.  
  684.    if(number > 1){
  685.       count = 1;
  686.       while(count < number){
  687.          count++;
  688.          mask_dilation(out_name, out_name, the_image,
  689.                         out_image, il, ie, ll, le,
  690.                         value, mask_type);
  691.       }  /* ends while */
  692.    }  /* ends if number > 1 */
  693.  
  694.    mask_erosion(out_name, out_name, the_image,
  695.                 out_image, il, ie, ll, le,
  696.                 value, mask_type);
  697.  
  698.    write_array_into_tiff_image(out_name, out_image,
  699.                                il, ie, ll, le);
  700.  
  701. }  /* ends closing */
  702.  
  703.  
  704.  
  705.  
  706.  
  707.      /*******************************************
  708.      *
  709.      *   get_shape_options(...
  710.      *
  711.      *   This function interacts with the user
  712.      *   to obtain the parameters for calling
  713.      *   the shape routines.
  714.      *
  715.      *******************************************/
  716.  
  717. get_shape_options(type, value, threshold, number)
  718.    char   type[];
  719.    int    *number, *threshold;
  720.    short  *value;
  721. {
  722.    int not_finished = 1, response;
  723.  
  724.    while(not_finished){
  725.  
  726.    printf("\nThe shape options are:");
  727.    printf("\n\t1. Type is %s", type);
  728.    printf("\n\t    recall: EROsion DILation Mask-ERosion"
  729.           "\n\t            Mask_DIlation INTerior-outline"
  730.           "\n\t            EXTerior-outline THInning"
  731.           "\n\t            Dilate-Not-Join OPEning"
  732.           "\n\t            CLOsing SPecial-Opening"
  733.           "\n\t            SPecial-Closing"
  734.           "\n\t            Euclidean-Distance-Measure"
  735.           "\n\t            Medial-Axis-Transform");
  736.    printf("\n\t2. value is %d", *value);
  737.    printf("\n\t3. threshold or mask type is %d",
  738.            *threshold);
  739.    printf("\n\t4. number of iterations is %d", *number);
  740.    printf("\n\t   (used only in opening and closing)");
  741.    printf("\n\nEnter choice (0 = no change) _\b");
  742.  
  743.       get_integer(&response);
  744.  
  745.       if(response == 0){
  746.         not_finished = 0;
  747.       }
  748.  
  749.       if(response == 1){
  750.       printf("\nEnter type of operation");
  751.       printf("\n\t    recall: EROsion DILation Mask-ERosion"
  752.              "\n\t            Mask_DIlation INTerior-outline"
  753.              "\n\t            EXTerior-outline THInning"
  754.              "\n\t            Dilate-Not-Join OPEning"
  755.              "\n\t            CLOsing SPecial-Opening"
  756.              "\n\t            SPecial-Closing"
  757.              "\n\t            Euclidean-Distance-Measure"
  758.              "\n\t            Medial-Axis-Transform");
  759.       printf("\n\t:");
  760.       gets(type);
  761.       }
  762.  
  763.       if(response == 2){
  764.          printf("\nEnter value: ___\b\b\b");
  765.          get_integer(value);
  766.       }
  767.  
  768.       if(response == 3){
  769.          printf("\nEnter threshold or mask type: ___");
  770.          printf("\b\b\b");
  771.          get_integer(threshold);
  772.       }
  773.  
  774.       if(response == 4){
  775.          printf("\nEnter number of iterations: ___");
  776.          printf("\b\b\b");
  777.          get_integer(number);
  778.       }
  779.  
  780.    }  /* ends while not_finished */
  781.  
  782. }  /* ends get_shape_options */
  783.  
  784.        /**********************************************
  785.        *
  786.        *       file d:\cips\skeleton.c
  787.        *
  788.        *       Functions: This file contains
  789.        *          thinning
  790.        *          can_thin
  791.        *          dilate_not_join
  792.        *          can_dilate
  793.        *          little_label_and_check
  794.        *          special_closing
  795.        *          special_opening
  796.        *          edm
  797.        *          distanc_8
  798.        *          mat
  799.        *          mat_d
  800.        *
  801.        *       Purpose:
  802.        *          These functions thin objects in
  803.        *          an image, dilate objects, and
  804.        *          perform opening and closing
  805.        *          without removing or joining
  806.        *          objects.
  807.        *
  808.        *       External Calls:
  809.        *          wtiff.c - round_off_image_size
  810.        *                    create_file_if_needed
  811.        *                    write_array_into_tiff_image
  812.        *          tiff.c - read_tiff_header
  813.        *          rtiff.c - read_tiff_image
  814.        *          numcvrt.c - get_integer
  815.        *
  816.        *
  817.        *       Modifications:
  818.        *          7 March 1993 - created
  819.        *
  820.        ************************************************/
  821.  
  822.  
  823.  
  824.  
  825.  
  826.  
  827.      /*******************************************
  828.      *
  829.      *   thinning(...
  830.      *
  831.      *   Use a variation of the grass fire
  832.      *   wave front approach.
  833.      *
  834.      *   Raster scan the image left to right
  835.      *   and examine and thin the left edge pixels
  836.      *   (a 0 to value transition).  Process them
  837.      *   normally and "save" the result.  Next,
  838.      *   raster scan the image right to left and
  839.      *   save.  Raster scan top to bottom and save.
  840.      *   Raster scan bottom to top and save.
  841.      *
  842.      *   That is one complete pass.
  843.      *
  844.      *   Keep track of pixels thinned for a
  845.      *   pass and quit when you make a complete
  846.      *   pass without thinning any pixels.
  847.      *
  848.      *******************************************/
  849.  
  850.  
  851. thinning(in_name, out_name, the_image, out_image,
  852.          il, ie, ll, le, value, threshold, once_only)
  853.    char   in_name[], out_name[];
  854.    int    il, ie, ll, le, once_only;
  855.    short  the_image[ROWS][COLS],
  856.           out_image[ROWS][COLS],
  857.           threshold, value;
  858. {
  859.    int    a, b, big_count, count, i, j, k,
  860.           not_finished;
  861.  
  862.    create_file_if_needed(in_name, out_name, out_image);
  863.  
  864.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  865.  
  866.  
  867.    for(i=0; i<ROWS; i++)
  868.       for(j=0; j<COLS; j++)
  869.          out_image[i][j] = the_image[i][j];
  870.  
  871.    not_finished = 1;
  872.    while(not_finished){
  873.  
  874.       if(once_only == 1)
  875.         not_finished = 0;
  876.       big_count = 0;
  877.  
  878.          /***************************
  879.          *
  880.          *   Scan left to right
  881.          *   Look for 0-value transition
  882.          *
  883.          ****************************/
  884.  
  885.       printf("\n");
  886.       for(i=1; i<ROWS-1; i++){
  887.          if( (i%10) == 0) printf("%3d", i);
  888.          for(j=1; j<COLS-1; j++){
  889.             if(the_image[i][j-1] == 0   &&
  890.                the_image[i][j]   == value){
  891.                count = 0;
  892.                for(a=-1; a<=1; a++){
  893.                    for(b=-1; b<=1; b++){
  894.                          if(the_image[i+a][j+b] == 0)
  895.                             count++;
  896.                    }  /*  ends loop over b */
  897.                }  /* ends loop over a */
  898.                if(count > threshold){
  899.                   if(can_thin(the_image, i, j, value)){
  900.                      out_image[i][j] = 0;
  901.                      big_count++;
  902.                   }  /* ends if can_thin */
  903.                }  /* ends if count > threshold */
  904.             }  /* ends if the_image == value */
  905.          }  /* ends loop over j */
  906.       }  /* ends loop over i */
  907.  
  908.          /**************************************
  909.          *
  910.          *   Copy the output back to the input.
  911.          *
  912.          **************************************/
  913.  
  914.       for(i=0; i<ROWS; i++)
  915.          for(j=0; j<COLS; j++)
  916.             the_image[i][j] = out_image[i][j];
  917.  
  918.  
  919.          /***************************
  920.          *
  921.          *   Scan right to left
  922.          *   Do this by scanning left
  923.          *   to right and look for
  924.          *   value-0 transition.
  925.          *
  926.          ****************************/
  927.  
  928.       printf("\n");
  929.       for(i=1; i<ROWS-1; i++){
  930.          if( (i%10) == 0) printf("%3d", i);
  931.          for(j=1; j<COLS-1; j++){
  932.             if(the_image[i][j+1] == 0   &&
  933.                the_image[i][j]   == value){
  934.                count = 0;
  935.                for(a=-1; a<=1; a++){
  936.                    for(b=-1; b<=1; b++){
  937.                          if(the_image[i+a][j+b] == 0)
  938.                             count++;
  939.                    }  /*  ends loop over b */
  940.                }  /* ends loop over a */
  941.                if(count > threshold){
  942.                   if(can_thin(the_image, i, j, value)){
  943.                      out_image[i][j] = 0;
  944.                      big_count++;
  945.                   }  /* ends if can_thin */
  946.                }  /* ends if count > threshold */
  947.             }  /* ends if the_image == value */
  948.          }  /* ends loop over j */
  949.       }  /* ends loop over i */
  950.  
  951.          /**************************************
  952.          *
  953.          *   Copy the output back to the input.
  954.          *
  955.          **************************************/
  956.  
  957.       for(i=0; i<ROWS; i++)
  958.          for(j=0; j<COLS; j++)
  959.             the_image[i][j] = out_image[i][j];
  960.  
  961.  
  962.          /***************************
  963.          *
  964.          *   Scan top to bottom
  965.          *   Look for 0-value transition
  966.          *
  967.          ****************************/
  968.  
  969.       printf("\n");
  970.       for(j=1; j<COLS-1; j++){
  971.          if( (j%10) == 0) printf("%3d", j);
  972.          for(i=1; i<ROWS-1; i++){
  973.             if(the_image[i-1][j] == 0   &&
  974.                the_image[i][j]   == value){
  975.                count = 0;
  976.                for(a=-1; a<=1; a++){
  977.                    for(b=-1; b<=1; b++){
  978.                          if(the_image[i+a][j+b] == 0)
  979.                             count++;
  980.                    }  /*  ends loop over b */
  981.                }  /* ends loop over a */
  982.                if(count > threshold){
  983.                   if(can_thin(the_image, i, j, value)){
  984.                      out_image[i][j] = 0;
  985.                      big_count++;
  986.                   }  /* ends if can_thin */
  987.                }  /* ends if count > threshold */
  988.             }  /* ends if the_image == value */
  989.          }  /* ends loop over i */
  990.       }  /* ends loop over j */
  991.  
  992.          /**************************************
  993.          *
  994.          *   Copy the output back to the input.
  995.          *
  996.          **************************************/
  997.  
  998.       for(i=0; i<ROWS; i++)
  999.          for(j=0; j<COLS; j++)
  1000.             the_image[i][j] = out_image[i][j];
  1001.  
  1002.  
  1003.  
  1004.          /***************************
  1005.          *
  1006.          *   Scan bottom to top
  1007.          *   Do this by scanning top
  1008.          *   to bottom and look for
  1009.          *   value-0 transition.
  1010.          *
  1011.          ****************************/
  1012.  
  1013.       printf("\n");
  1014.       for(j=1; j<COLS-1; j++){
  1015.          if( (j%10) == 0) printf("%3d", j);
  1016.          for(i=1; i<ROWS-1; i++){
  1017.             if(the_image[i+1][j] == 0   &&
  1018.                the_image[i][j]   == value){
  1019.                count = 0;
  1020.                for(a=-1; a<=1; a++){
  1021.                    for(b=-1; b<=1; b++){
  1022.                          if(the_image[i+a][j+b] == 0)
  1023.                             count++;
  1024.                    }  /*  ends loop over b */
  1025.                }  /* ends loop over a */
  1026.                if(count > threshold){
  1027.                   if(can_thin(the_image, i, j, value)){
  1028.                      out_image[i][j] = 0;
  1029.                      big_count++;
  1030.                   }  /* ends if can_thin */
  1031.                }  /* ends if count > threshold */
  1032.             }  /* ends if the_image == value */
  1033.          }  /* ends loop over i */
  1034.       }  /* ends loop over j */
  1035.  
  1036.          /**************************************
  1037.          *
  1038.          *   Copy the output back to the input.
  1039.          *
  1040.          **************************************/
  1041.  
  1042.       for(i=0; i<ROWS; i++)
  1043.          for(j=0; j<COLS; j++)
  1044.             the_image[i][j] = out_image[i][j];
  1045.  
  1046.          /**************************************
  1047.          *
  1048.          *   Now look at the result of this big
  1049.          *   pass through the image.
  1050.          *
  1051.          ***************************************/
  1052.  
  1053.       printf("\n\nThinned %d pixels", big_count);
  1054.       if(big_count == 0)
  1055.          not_finished = 0;
  1056.       else{
  1057.          for(i=0; i<ROWS; i++)
  1058.             for(j=0; j<COLS; j++)
  1059.                the_image[i][j] = out_image[i][j];
  1060.       }  /* ends else */
  1061.  
  1062.    }  /* ends while not_finished */
  1063.  
  1064.    fix_edges(out_image, 3);
  1065.    write_array_into_tiff_image(out_name, out_image,
  1066.                                il, ie, ll, le);
  1067. }  /* ends thinning */
  1068.  
  1069.  
  1070.  
  1071.  
  1072.  
  1073.      /*******************************************
  1074.      *
  1075.      *   can_thin(...
  1076.      *
  1077.      *   Look at the neighbors of the center pixel.
  1078.      *   If a neighbor == value, then it must
  1079.      *   have a neighbor == value other than the
  1080.      *   center pixel.
  1081.      *
  1082.      *   Procedure:
  1083.      *   . Copy the 3x3 area surrounding pixel
  1084.      *     i,j to a temp array.
  1085.      *   . Set the center pixel to zero.
  1086.      *   . Look at each non-zero pixel in temp.
  1087.      *      . If you cannot find a non-zero
  1088.      *        neighbor.
  1089.      *      . Then you cannot thin.
  1090.      *
  1091.      *******************************************/
  1092.  
  1093. can_thin(the_image, i, j, value)
  1094.    int   i, j;
  1095.    short the_image[ROWS][COLS], value;
  1096. {
  1097.    int   a, b, c, d, count,
  1098.          no_neighbor, one=1, zero=0;
  1099.    short temp[3][3];
  1100.  
  1101.        /**************************************
  1102.        *
  1103.        *   Copy the center pixel and its
  1104.        *   neighbors to the temp array.
  1105.        *
  1106.        ***************************************/
  1107.  
  1108.    for(a=-1; a<2; a++)
  1109.       for(b=-1; b<2; b++)
  1110.          temp[a+1][b+1] = the_image[i+a][b+j];
  1111.  
  1112.        /**************************************
  1113.        *
  1114.        *   Set the center of temp to 0.
  1115.        *
  1116.        ***************************************/
  1117.  
  1118.    temp[1][1] = 0;
  1119.  
  1120.        /**************************************
  1121.        *
  1122.        *   Check the non-zero pixels in temp.
  1123.        *
  1124.        ***************************************/
  1125.  
  1126.    for(a=0; a<3; a++){
  1127.       for(b=0; b<3; b++){
  1128.          if(temp[a][b] == value){
  1129.             temp[a][b] = 0;
  1130.  
  1131.                 /**************************************
  1132.                 *
  1133.                 *   Check the neighbors of this pixel
  1134.                 *   If there is a single non-zero
  1135.                 *   neighbor, set no_neighbor = 0.
  1136.                 *
  1137.                 ***************************************/
  1138.  
  1139.             no_neighbor = 1;
  1140.             for(c=-1; c<2; c++){
  1141.                for(d=-1; d<2; d++){
  1142.                   if( ((a+c) >= 0)   &&
  1143.                       ((a+c) <= 2)   &&
  1144.                       ((b+d) >= 0)   &&
  1145.                       ((b+d) <= 2)){
  1146.                      if(temp[a+c][b+d] == value){
  1147.                         no_neighbor = 0;
  1148.                      }  /* ends if temp == value */
  1149.                   }  /* ends if part of temp array */
  1150.                }  /* ends loop over d */
  1151.             }  /* ends loop over c */
  1152.             temp[a][b] = value;
  1153.  
  1154.                 /**************************************
  1155.                 *
  1156.                 *   If the non-zero pixel did not
  1157.                 *   have any non-zero neighbors,
  1158.                 *   no_neighbor still equals 1,
  1159.                 *   and we cannot thin, so return
  1160.                 *   zero.
  1161.                 *
  1162.                 ***************************************/
  1163.  
  1164.             if(no_neighbor){
  1165.                return(zero);
  1166.             }
  1167.          }  /* ends if temp[a][b] == value */
  1168.       }  /* ends loop over b */
  1169.    }  /* ends loop over a */
  1170.  
  1171.        /**************************************
  1172.        *
  1173.        *   First, ensure the object is more
  1174.        *   than two wide.  If it is two wide,
  1175.        *   you will thin out the entire object.
  1176.        *   Check in all eight directions.
  1177.        *   If the distance to a zero is 0 or
  1178.        *   >= 2, then ok you can thin so go
  1179.        *   on to the remainder of this routine.
  1180.        *   If not, you cannot thin so return
  1181.        *   zero.
  1182.        *
  1183.        ***************************************/
  1184.  
  1185.    return(one);
  1186.  
  1187. }  /* ends can_thin */
  1188.  
  1189.  
  1190.  
  1191.  
  1192.  
  1193.      /*******************************************
  1194.      *
  1195.      *   dilate_not_join(...
  1196.      *
  1197.      *   Use a variation of the grass fire
  1198.      *   wave front approach.
  1199.      *
  1200.      *   Raster scan the image left to right
  1201.      *   and examine and dilate the left edge pixels
  1202.      *   (a value to 0 transition).  Process them
  1203.      *   normally and "save" the result.  Next,
  1204.      *   raster scan the image right to left and
  1205.      *   save.  Raster scan top to bottom and save.
  1206.      *   Raster scan bottom to top and save.
  1207.      *
  1208.      *   That is one complete pass.
  1209.      *
  1210.      *******************************************/
  1211.  
  1212. dilate_not_join(in_name, out_name, the_image, out_image,
  1213.                 il, ie, ll, le, value, threshold)
  1214.    char   in_name[], out_name[];
  1215.    int    il, ie, ll, le;
  1216.    short  the_image[ROWS][COLS],
  1217.           out_image[ROWS][COLS],
  1218.           threshold, value;
  1219. {
  1220.    int    a, b, count, i, j, k;
  1221.  
  1222.    create_file_if_needed(in_name, out_name, out_image);
  1223.  
  1224.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  1225.  
  1226.  
  1227.    for(i=0; i<ROWS; i++)
  1228.       for(j=0; j<COLS; j++)
  1229.          out_image[i][j] = the_image[i][j];
  1230.  
  1231.          /***************************
  1232.          *
  1233.          *   Scan left to right
  1234.          *   Look for value-0 transition
  1235.          *
  1236.          ****************************/
  1237.  
  1238.       printf("\n");
  1239.       for(i=1; i<ROWS-1; i++){
  1240.          if( (i%10) == 0) printf("%3d", i);
  1241.          for(j=1; j<COLS-1; j++){
  1242.             if(the_image[i][j-1] == value  &&
  1243.                the_image[i][j]   == 0){
  1244.                count = 0;
  1245.                for(a=-1; a<=1; a++){
  1246.                    for(b=-1; b<=1; b++){
  1247.                          if(the_image[i+a][j+b]==value)
  1248.                             count++;
  1249.                    }  /*  ends loop over b */
  1250.                }  /* ends loop over a */
  1251.                if(count > threshold){
  1252.                   if(can_dilate(the_image,i,j,value)){
  1253.                      out_image[i][j] = value;
  1254.                   }  /* ends if can_dilate */
  1255.                }  /* ends if count > threshold */
  1256.             }  /* ends if the_image == value */
  1257.          }  /* ends loop over j */
  1258.       }  /* ends loop over i */
  1259.  
  1260.          /**************************************
  1261.          *
  1262.          *   Copy the output back to the input.
  1263.          *
  1264.          **************************************/
  1265.  
  1266.       for(i=0; i<ROWS; i++)
  1267.          for(j=0; j<COLS; j++)
  1268.             the_image[i][j] = out_image[i][j];
  1269.  
  1270.  
  1271.          /***************************
  1272.          *
  1273.          *   Scan right to left
  1274.          *   Do this by scanning left
  1275.          *   to right and look for
  1276.          *   0-value transition.
  1277.          *
  1278.          ****************************/
  1279.  
  1280.       printf("\n");
  1281.       for(i=1; i<ROWS-1; i++){
  1282.          if( (i%10) == 0) printf("%3d", i);
  1283.          for(j=1; j<COLS-1; j++){
  1284.             if(the_image[i][j+1] == value   &&
  1285.                the_image[i][j]   == 0){
  1286.                count = 0;
  1287.                for(a=-1; a<=1; a++){
  1288.                    for(b=-1; b<=1; b++){
  1289.                          if(the_image[i+a][j+b]==value)
  1290.                             count++;
  1291.                    }  /*  ends loop over b */
  1292.                }  /* ends loop over a */
  1293.                if(count > threshold){
  1294.                   if(can_dilate(the_image,i,j,value)){
  1295.                      out_image[i][j] = value;
  1296.                   }  /* ends if can_dilate */
  1297.                }  /* ends if count > threshold */
  1298.             }  /* ends if the_image == value */
  1299.          }  /* ends loop over j */
  1300.       }  /* ends loop over i */
  1301.  
  1302.          /**************************************
  1303.          *
  1304.          *   Copy the output back to the input.
  1305.          *
  1306.          **************************************/
  1307.  
  1308.       for(i=0; i<ROWS; i++)
  1309.          for(j=0; j<COLS; j++)
  1310.             the_image[i][j] = out_image[i][j];
  1311.  
  1312.  
  1313.          /***************************
  1314.          *
  1315.          *   Scan top to bottom
  1316.          *   Look for value-0 transition
  1317.          *
  1318.          ****************************/
  1319.  
  1320.       printf("\n");
  1321.       for(j=1; j<COLS-1; j++){
  1322.          if( (j%10) == 0) printf("%3d", j);
  1323.          for(i=1; i<ROWS-1; i++){
  1324.             if(the_image[i-1][j] == value   &&
  1325.                the_image[i][j]   == 0){
  1326.                count = 0;
  1327.                for(a=-1; a<=1; a++){
  1328.                    for(b=-1; b<=1; b++){
  1329.                          if(the_image[i+a][j+b]==value)
  1330.                             count++;
  1331.                    }  /*  ends loop over b */
  1332.                }  /* ends loop over a */
  1333.                if(count > threshold){
  1334.                   if(can_dilate(the_image,i,j,value)){
  1335.                      out_image[i][j] = value;
  1336.                   }  /* ends if can_dilate */
  1337.                }  /* ends if count > threshold */
  1338.             }  /* ends if the_image == value */
  1339.          }  /* ends loop over i */
  1340.       }  /* ends loop over j */
  1341.  
  1342.          /**************************************
  1343.          *
  1344.          *   Copy the output back to the input.
  1345.          *
  1346.          **************************************/
  1347.  
  1348.       for(i=0; i<ROWS; i++)
  1349.          for(j=0; j<COLS; j++)
  1350.             the_image[i][j] = out_image[i][j];
  1351.  
  1352.  
  1353.  
  1354.          /***************************
  1355.          *
  1356.          *   Scan bottom to top
  1357.          *   Do this by scanning top
  1358.          *   to bottom and look for
  1359.          *   0-value transition.
  1360.          *
  1361.          ****************************/
  1362.  
  1363.       printf("\n");
  1364.       for(j=1; j<COLS-1; j++){
  1365.          if( (j%10) == 0) printf("%3d", j);
  1366.          for(i=1; i<ROWS-1; i++){
  1367.             if(the_image[i+1][j] == value   &&
  1368.                the_image[i][j]   == 0){
  1369.                count = 0;
  1370.                for(a=-1; a<=1; a++){
  1371.                    for(b=-1; b<=1; b++){
  1372.                          if(the_image[i+a][j+b]==value)
  1373.                             count++;
  1374.                    }  /*  ends loop over b */
  1375.                }  /* ends loop over a */
  1376.                if(count > threshold){
  1377.                   if(can_dilate(the_image,i,j,value)){
  1378.                      out_image[i][j] = value;
  1379.                   }  /* ends if can_dilate */
  1380.                }  /* ends if count > threshold */
  1381.             }  /* ends if the_image == value */
  1382.          }  /* ends loop over i */
  1383.       }  /* ends loop over j */
  1384.  
  1385.          /**************************************
  1386.          *
  1387.          *   Copy the output back to the input.
  1388.          *
  1389.          **************************************/
  1390.  
  1391.       for(i=0; i<ROWS; i++)
  1392.          for(j=0; j<COLS; j++)
  1393.             the_image[i][j] = out_image[i][j];
  1394.  
  1395.  
  1396.    fix_edges(out_image, 3);
  1397.  
  1398.    write_array_into_tiff_image(out_name, out_image,
  1399.                                il, ie, ll, le);
  1400.  
  1401. }  /* ends dilate_not_join */
  1402.  
  1403.  
  1404.  
  1405.  
  1406.  
  1407.      /*******************************************
  1408.      *
  1409.      *   can_dilate(...
  1410.      *
  1411.      *   This function decides if you can dilate
  1412.      *   (set to value) a pixel without joining
  1413.      *   two separate objects in a 3x3 area.
  1414.      *
  1415.      *   First, you grow regions inside the 3x3
  1416.      *   area.  Next, check if the center pixel
  1417.      *   has neighbors with differing values.
  1418.      *   If it does, you cannot dilate it because
  1419.      *   that would join two separate objects.
  1420.      *
  1421.      *******************************************/
  1422.  
  1423. can_dilate(the_image, i, j, value)
  1424.    int   i, j;
  1425.    short the_image[ROWS][COLS], value;
  1426. {
  1427.    int   a, b, c, d, count, found=0,
  1428.          no_neighbor,
  1429.          stack_pointer=-1,
  1430.          stack_empty=1,
  1431.          stack[12][2],
  1432.          pop_a, pop_b,
  1433.          one=1,
  1434.          zero=0;
  1435.    short first_value, label = 2, temp[3][3];
  1436.  
  1437.        /**************************************
  1438.        *
  1439.        *   Copy the center pixel and its
  1440.        *   neighbors to the temp array.
  1441.        *
  1442.        ***************************************/
  1443.  
  1444.    for(a=-1; a<2; a++)
  1445.       for(b=-1; b<2; b++)
  1446.          temp[a+1][b+1] = the_image[i+a][b+j];
  1447.  
  1448.        /**************************************
  1449.        *
  1450.        *   Grow objects inside the temp array.
  1451.        *
  1452.        ***************************************/
  1453.  
  1454.    for(a=0; a<3; a++){
  1455.       for(b=0; b<3; b++){
  1456.          stack_empty   = 1;
  1457.          stack_pointer = -1;
  1458.          if(temp[a][b] == value){
  1459.             little_label_and_check(temp, stack, label,
  1460.                                    &stack_empty,
  1461.                                    &stack_pointer,
  1462.                                    a, b, value);
  1463.             found = 1;
  1464.          }  /* ends if temp == value */
  1465.  
  1466.          while(stack_empty == 0){
  1467.             pop_a = stack[stack_pointer][0]; /* POP */
  1468.             pop_b = stack[stack_pointer][1]; /* POP */
  1469.             --stack_pointer;
  1470.             if(stack_pointer <= 0){
  1471.                stack_pointer = 0;
  1472.                stack_empty   = 1;
  1473.             }  /* ends if stack_pointer */
  1474.             little_label_and_check(temp, stack, label,
  1475.                                    &stack_empty,
  1476.                                    &stack_pointer,
  1477.                                    pop_a, pop_b, value);
  1478.          }  /* ends while stack_empty == 0 */
  1479.  
  1480.          if(found){
  1481.             found = 0;
  1482.             label++;
  1483.          }  /* ends if object_found */
  1484.       }  /* ends loop over b */
  1485.    }  /* ends loop over a */
  1486.  
  1487.        /**************************************
  1488.        *
  1489.        *   Look at the center pixel.  If it
  1490.        *   has two non-zero neigbors whose
  1491.        *   pixels are not the same, then
  1492.        *   you cannot dilate.
  1493.        *
  1494.        ***************************************/
  1495.  
  1496.    first_value = -1;
  1497.    for(a=0; a<3; a++){
  1498.       for(b=0; b<3; b++){
  1499.          if(temp[a][b]  != 0 &&
  1500.             first_value == -1){
  1501.             first_value = temp[a][b];
  1502.          }
  1503.          if(temp[a][b]  != 0  &&
  1504.             first_value != -1){
  1505.             if(temp[a][b] != first_value){
  1506.                return(zero);
  1507.             }
  1508.          }
  1509.       }  /* ends loop over b */
  1510.    }  /* ends loop over a */
  1511.  
  1512.    return(one);
  1513.  
  1514. }  /* ends can_dilate */
  1515.  
  1516.  
  1517.  
  1518.  
  1519.  
  1520.      /*******************************************
  1521.      *
  1522.      *   little_label_and_check(...
  1523.      *
  1524.      *   This function labels the objects in
  1525.      *   in a 3x3 area.
  1526.      *
  1527.      *******************************************/
  1528.  
  1529. little_label_and_check(temp, stack, label, stack_empty,
  1530.                        stack_pointer, a, b, value)
  1531.    int   a, b, stack[12][2], 
  1532.          *stack_empty, *stack_pointer;
  1533.    short temp[3][3], label, value;
  1534. {
  1535.    int c, d;
  1536.  
  1537.    temp[a][b] = label;
  1538.    for(c=a-1; c<=a+1; c++){
  1539.       for(d=b-1; d<=b+1; d++){
  1540.          if(c >= 0      &&
  1541.             c <= 2      &&
  1542.             d >= 0      &&
  1543.             d <= 2)
  1544.             if(temp[c][d] == value){  /* PUSH */
  1545.                *stack_pointer = *stack_pointer + 1;
  1546.                stack[*stack_pointer][0] = c;
  1547.                stack[*stack_pointer][1] = d;
  1548.                *stack_empty = 0;
  1549.             }  /* ends if temp == value */
  1550.       }  /* ends loop over d */
  1551.    }  /* ends loop over c */
  1552.  
  1553. }  /* ends little_label_and_check */
  1554.  
  1555.  
  1556.  
  1557.  
  1558.  
  1559.      /*******************************************
  1560.      *
  1561.      *   special_closing(...
  1562.      *
  1563.      *   Closing is dilation followed by erosion.
  1564.      *   This routine will use the dilate_not_join
  1565.      *   dilation routine.  This will not allow
  1566.      *   two separate objects to join.
  1567.      *
  1568.      *   The number parameter specifies how
  1569.      *   dilations to perform before doing one
  1570.      *   erosion.
  1571.      *
  1572.      *******************************************/
  1573.  
  1574. special_closing(in_name, out_name, the_image,
  1575.                 out_image, il, ie, ll, le,
  1576.                 value, threshold, number)
  1577.    char   in_name[], out_name[];
  1578.    int    il, ie, ll, le, number;
  1579.    short  the_image[ROWS][COLS],
  1580.           out_image[ROWS][COLS],
  1581.           threshold, value;
  1582. {
  1583.    int    a, b, count, i, j, k;
  1584.  
  1585.    create_file_if_needed(in_name, out_name, out_image);
  1586.  
  1587.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  1588.  
  1589.    dilate_not_join(in_name, out_name, the_image,
  1590.                    out_image, il, ie, ll, le,
  1591.                    value, threshold);
  1592.  
  1593.    if(number > 1){
  1594.       count = 1;
  1595.       while(count < number){
  1596.          count++;
  1597.          dilate_not_join(out_name, out_name, the_image,
  1598.                          out_image, il, ie, ll, le,
  1599.                          value, threshold);
  1600.       }  /* ends while */
  1601.    }  /* ends if number > 1 */
  1602.  
  1603.    erosion(out_name, out_name, the_image,
  1604.            out_image, il, ie, ll, le,
  1605.            value, threshold);
  1606.  
  1607.    write_array_into_tiff_image(out_name, out_image,
  1608.                                il, ie, ll, le);
  1609.  
  1610. }  /* ends special_closing */
  1611.  
  1612.  
  1613.  
  1614.  
  1615.  
  1616.      /*******************************************
  1617.      *
  1618.      *   special_opening(...
  1619.      *
  1620.      *   Opening is erosion followed by dilation.
  1621.      *   This routine will use the thinning
  1622.      *   erosion routine.  This will not allow
  1623.      *   an object to erode to nothing.
  1624.      *
  1625.      *   The number parameter specifies how
  1626.      *   erosions to perform before doing one
  1627.      *   dilation.
  1628.      *
  1629.      *******************************************/
  1630.  
  1631. special_opening(in_name, out_name, the_image,
  1632.                 out_image, il, ie, ll, le,
  1633.                 value, threshold, number)
  1634.    char   in_name[], out_name[];
  1635.    int    il, ie, ll, le, number;
  1636.    short  the_image[ROWS][COLS],
  1637.           out_image[ROWS][COLS],
  1638.           threshold, value;
  1639. {
  1640.    int    a, b, count, i, j, k;
  1641.  
  1642.    create_file_if_needed(in_name, out_name, out_image);
  1643.  
  1644.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  1645.  
  1646.    thinning(in_name, out_name, the_image,
  1647.             out_image, il, ie, ll, le,
  1648.             value, threshold, 1);
  1649.  
  1650.    if(number > 1){
  1651.       count = 1;
  1652.       while(count < number){
  1653.          count++;
  1654.          thinning(out_name, out_name, the_image,
  1655.                   out_image, il, ie, ll, le,
  1656.                   value, threshold, 1);
  1657.       }  /* ends while */
  1658.    }  /* ends if number > 1 */
  1659.  
  1660.    dilation(out_name, out_name, the_image,
  1661.             out_image, il, ie, ll, le,
  1662.             value, threshold);
  1663.  
  1664.    write_array_into_tiff_image(out_name, out_image,
  1665.                                il, ie, ll, le);
  1666.  
  1667. }  /* ends special_opening */
  1668.  
  1669.  
  1670.  
  1671.  
  1672.  
  1673.      /*******************************************
  1674.      *
  1675.      *   edm(..
  1676.      *
  1677.      *   This function calculates the Euclidean
  1678.      *   distance measure for objects in an image.
  1679.      *   It calculates the distance from any
  1680.      *   pixel=value to the nearest zero pixel
  1681.      *
  1682.      *******************************************/
  1683.  
  1684.  
  1685. edm(in_name, out_name, the_image, out_image,
  1686.           il, ie, ll, le, value)
  1687.    char   in_name[], out_name[];
  1688.    int    il, ie, ll, le;
  1689.    short  the_image[ROWS][COLS],
  1690.           out_image[ROWS][COLS],
  1691.           value;
  1692. {
  1693.    int    a, b, count, i, j, k;
  1694.  
  1695.    create_file_if_needed(in_name, out_name, out_image);
  1696.  
  1697.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  1698.  
  1699.    for(i=0; i<ROWS; i++)
  1700.       for(j=0; j<COLS; j++)
  1701.          out_image[i][j] = 0;
  1702.  
  1703.       /***************************
  1704.       *
  1705.       *   Loop over image array
  1706.       *
  1707.       ****************************/
  1708.  
  1709.    printf("\n");
  1710.  
  1711.    for(i=0; i<ROWS; i++){
  1712.       if( (i%10) == 0) printf("%3d", i);
  1713.       for(j=0; j<COLS; j++){
  1714.          if(the_image[i][j] == value)
  1715.             out_image[i][j] = distance_8(the_image, 
  1716.                                          i, j, value);
  1717.       }  /* ends loop over j */
  1718.    }  /* ends loop over i */
  1719.  
  1720.    write_array_into_tiff_image(out_name, out_image,
  1721.                                il, ie, ll, le);
  1722.  
  1723. }  /* ends edm */
  1724.  
  1725.  
  1726.  
  1727.      /*******************************************
  1728.      *
  1729.      *   distance_8(..
  1730.      *
  1731.      *   This function finds the distance from
  1732.      *   a pixel to the nearest zero pixel.
  1733.      *   It search in all eight directions.
  1734.      *
  1735.      *******************************************/
  1736.  
  1737. distance_8(the_image, a, b, value)
  1738.    int   a, b;
  1739.    short the_image[ROWS][COLS], value;
  1740. {
  1741.    int i, j, measuring;
  1742.    short dist1  = 0,
  1743.          dist2  = 0,
  1744.          dist3  = 0,
  1745.          dist4  = 0,
  1746.          dist5  = 0,
  1747.          dist6  = 0,
  1748.          dist7  = 0,
  1749.          dist8  = 0,
  1750.          result = 0;
  1751.  
  1752.       /* straight up */
  1753.    measuring = 1;
  1754.    i = a;
  1755.    j = b;
  1756.    while(measuring){
  1757.       i--;
  1758.       if(i >= 0){
  1759.          if(the_image[i][j] == value)
  1760.             dist1++;
  1761.          else
  1762.             measuring = 0;
  1763.       }
  1764.       else
  1765.          measuring = 0;
  1766.    }  /* ends while measuring */
  1767.    result = dist1;
  1768.  
  1769.       /* straight down */
  1770.    measuring = 1;
  1771.    i = a;
  1772.    j = b;
  1773.    while(measuring){
  1774.       i++;
  1775.       if(i <= ROWS-1){
  1776.          if(the_image[i][j] == value)
  1777.             dist2++;
  1778.          else
  1779.             measuring = 0;
  1780.       }
  1781.       else
  1782.          measuring = 0;
  1783.    }  /* ends while measuring */
  1784.    if(dist2 <= result)
  1785.       result = dist2;
  1786.  
  1787.       /* straight left */
  1788.    measuring = 1;
  1789.    i = a;
  1790.    j = b;
  1791.    while(measuring){
  1792.       j--;
  1793.       if(j >= 0){
  1794.          if(the_image[i][j] == value)
  1795.             dist3++;
  1796.          else
  1797.             measuring = 0;
  1798.       }
  1799.       else
  1800.          measuring = 0;
  1801.    }  /* ends while measuring */
  1802.    if(dist3 <= result)
  1803.       result = dist3;
  1804.  
  1805.       /* straight right */
  1806.    measuring = 1;
  1807.    i = a;
  1808.    j = b;
  1809.    while(measuring){
  1810.       j++;
  1811.       if(j <= COLS-1){
  1812.          if(the_image[i][j] == value)
  1813.             dist4++;
  1814.          else
  1815.             measuring = 0;
  1816.       }
  1817.       else
  1818.          measuring = 0;
  1819.    }  /* ends while measuring */
  1820.    if(dist4 <= result)
  1821.       result = dist4;
  1822.  
  1823.       /* left and up */
  1824.    measuring = 1;
  1825.    i = a;
  1826.    j = b;
  1827.    while(measuring){
  1828.       j--;
  1829.       i--;
  1830.       if(j >= 0 && i>=0){
  1831.          if(the_image[i][j] == value)
  1832.             dist5++;
  1833.          else
  1834.             measuring = 0;
  1835.       }
  1836.       else
  1837.          measuring = 0;
  1838.    }  /* ends while measuring */
  1839.    dist5 = (dist5*14)/10;
  1840.    if(dist5 <= result)
  1841.       result = dist5;
  1842.  
  1843.       /* right and up */
  1844.    measuring = 1;
  1845.    i = a;
  1846.    j = b;
  1847.    while(measuring){
  1848.       j++;
  1849.       i--;
  1850.       if(j <=COLS-1 && i>=0){
  1851.          if(the_image[i][j] == value)
  1852.             dist6++;
  1853.          else
  1854.             measuring = 0;
  1855.       }
  1856.       else
  1857.          measuring = 0;
  1858.    }  /* ends while measuring */
  1859.    dist6 = (dist6*14)/10;
  1860.    if(dist6 <= result)
  1861.       result = dist6;
  1862.  
  1863.       /* right and down */
  1864.    measuring = 1;
  1865.    i = a;
  1866.    j = b;
  1867.    while(measuring){
  1868.       j++;
  1869.       i++;
  1870.       if(j <=COLS-1 && i<=ROWS-1){
  1871.          if(the_image[i][j] == value)
  1872.             dist7++;
  1873.          else
  1874.             measuring = 0;
  1875.       }
  1876.       else
  1877.          measuring = 0;
  1878.    }  /* ends while measuring */
  1879.    dist7 = (dist7*14)/10;
  1880.    if(dist7 <= result)
  1881.       result = dist7;
  1882.  
  1883.       /* left and down */
  1884.    measuring = 1;
  1885.    i = a;
  1886.    j = b;
  1887.    while(measuring){
  1888.       j--;
  1889.       i++;
  1890.       if(j >=0 && i<=ROWS-1){
  1891.          if(the_image[i][j] == value)
  1892.             dist8++;
  1893.          else
  1894.             measuring = 0;
  1895.       }
  1896.       else
  1897.          measuring = 0;
  1898.    }  /* ends while measuring */
  1899.    dist8 = (dist8*14)/10;
  1900.    if(dist8 <= result)
  1901.       result = dist8;
  1902.  
  1903.    return(result);
  1904. }  /* ends distance_8 */
  1905.  
  1906.  
  1907.  
  1908.  
  1909.  
  1910.      /*******************************************
  1911.      *
  1912.      *   mat(..
  1913.      *
  1914.      *   This function finds the medial axis
  1915.      *   transform for objects in an image.
  1916.      *   The mat are those points that are
  1917.      *   minimally distant to more than one
  1918.      *   boundary point.
  1919.      *
  1920.      *******************************************/
  1921.  
  1922.  
  1923. mat(in_name, out_name, the_image, out_image,
  1924.     il, ie, ll, le, value)
  1925.    char   in_name[], out_name[];
  1926.    int    il, ie, ll, le;
  1927.    short  the_image[ROWS][COLS],
  1928.           out_image[ROWS][COLS],
  1929.           value;
  1930. {
  1931.    int    a, b, count, i, j, k,
  1932.           length, width;
  1933.  
  1934.    create_file_if_needed(in_name, out_name, out_image);
  1935.  
  1936.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  1937.  
  1938.    for(i=0; i<ROWS; i++)
  1939.       for(j=0; j<COLS; j++)
  1940.          out_image[i][j] = 0;
  1941.  
  1942.       /***************************
  1943.       *
  1944.       *   Loop over image array
  1945.       *
  1946.       ****************************/
  1947.  
  1948.    printf("\n");
  1949.  
  1950.    for(i=0; i<ROWS; i++){
  1951.       if( (i%10) == 0) printf("%3d", i);
  1952.       for(j=0; j<COLS; j++){
  1953.          if(the_image[i][j] == value)
  1954.             out_image[i][j] = mat_d(the_image, 
  1955.                                     i, j, value);
  1956.       }  /* ends loop over j */
  1957.    }  /* ends loop over i */
  1958.  
  1959.    write_array_into_tiff_image(out_name, out_image,
  1960.                                il, ie, ll, le);
  1961.  
  1962. }  /* ends mat */
  1963.  
  1964.  
  1965.  
  1966.      /*******************************************
  1967.      *
  1968.      *   mat_d(..
  1969.      *
  1970.      *   This function helps find the medial
  1971.      *   axis transform.
  1972.      *
  1973.      *   This function measures the distances
  1974.      *   from the point to a zero pixel in all
  1975.      *   eight directions.  Look for the two
  1976.      *   shortest distances in the eight distances.
  1977.      *   If the two shortest distances are
  1978.      *   equal, then the point in question
  1979.      *   is minimally distant to more than one
  1980.      *   boundary point.  Therefore, it is
  1981.      *   on the medial axis so return a value.
  1982.      *   Otherwise, return zero.
  1983.      *
  1984.      *******************************************/
  1985.  
  1986. mat_d(the_image, a, b, value)
  1987.    int   a, b;
  1988.    short the_image[ROWS][COLS], value;
  1989. {
  1990.    int i, j, measuring;
  1991.    short dist1  = 0,
  1992.          dist2  = 0,
  1993.          dist3  = 0,
  1994.          dist4  = 0,
  1995.          dist5  = 0,
  1996.          dist6  = 0,
  1997.          dist7  = 0,
  1998.          dist8  = 0,
  1999.          min1   = 255,
  2000.          min2   = 255,
  2001.          result = 0;
  2002.  
  2003.       /* straight up */
  2004.    measuring = 1;
  2005.    i = a;
  2006.    j = b;
  2007.    while(measuring){
  2008.       i--;
  2009.       if(i >= 0){
  2010.          if(the_image[i][j] == value)
  2011.             dist1++;
  2012.          else
  2013.             measuring = 0;
  2014.       }
  2015.       else
  2016.          measuring = 0;
  2017.    }  /* ends while measuring */
  2018.    result = dist1;
  2019.    min1   = dist1;
  2020.  
  2021.       /* straight down */
  2022.    measuring = 1;
  2023.    i = a;
  2024.    j = b;
  2025.    while(measuring){
  2026.       i++;
  2027.       if(i <= ROWS-1){
  2028.          if(the_image[i][j] == value)
  2029.             dist2++;
  2030.          else
  2031.             measuring = 0;
  2032.       }
  2033.       else
  2034.          measuring = 0;
  2035.    }  /* ends while measuring */
  2036.    if(dist2 <= result)
  2037.       result = dist2;
  2038.    if(dist2 < min1){
  2039.       min2 = min1;
  2040.       min1 = dist2;
  2041.    }
  2042.    else
  2043.       if(dist2 < min2)
  2044.          min2 = dist2;
  2045.  
  2046.       /* straight left */
  2047.    measuring = 1;
  2048.    i = a;
  2049.    j = b;
  2050.    while(measuring){
  2051.       j--;
  2052.       if(j >= 0){
  2053.          if(the_image[i][j] == value)
  2054.             dist3++;
  2055.          else
  2056.             measuring = 0;
  2057.       }
  2058.       else
  2059.          measuring = 0;
  2060.    }  /* ends while measuring */
  2061.    if(dist3 <= result)
  2062.       result = dist3;
  2063.    if(dist3 < min1){
  2064.       min2 = min1;
  2065.       min1 = dist3;
  2066.    }
  2067.    else
  2068.       if(dist3 < min2)
  2069.          min2 = dist3;
  2070.  
  2071.       /* straight right */
  2072.    measuring = 1;
  2073.    i = a;
  2074.    j = b;
  2075.    while(measuring){
  2076.       j++;
  2077.       if(j <= COLS-1){
  2078.          if(the_image[i][j] == value)
  2079.             dist4++;
  2080.          else
  2081.             measuring = 0;
  2082.       }
  2083.       else
  2084.          measuring = 0;
  2085.    }  /* ends while measuring */
  2086.    if(dist4 <= result)
  2087.       result = dist4;
  2088.    if(dist4 < min1){
  2089.       min2 = min1;
  2090.       min1 = dist4;
  2091.    }
  2092.    else
  2093.       if(dist4 < min2)
  2094.          min2 = dist4;
  2095.  
  2096.       /* left and up */
  2097.    measuring = 1;
  2098.    i = a;
  2099.    j = b;
  2100.    while(measuring){
  2101.       j--;
  2102.       i--;
  2103.       if(j >= 0 && i>=0){
  2104.          if(the_image[i][j] == value)
  2105.             dist5++;
  2106.          else
  2107.             measuring = 0;
  2108.       }
  2109.       else
  2110.          measuring = 0;
  2111.    }  /* ends while measuring */
  2112.    dist5 = ((dist5*14)+7)/10;
  2113.    if(dist5 <= result)
  2114.       result = dist5;
  2115.    if(dist5 < min1){
  2116.       min2 = min1;
  2117.       min1 = dist5;
  2118.    }
  2119.    else
  2120.       if(dist5 < min2)
  2121.          min2 = dist5;
  2122.  
  2123.       /* right and up */
  2124.    measuring = 1;
  2125.    i = a;
  2126.    j = b;
  2127.    while(measuring){
  2128.       j++;
  2129.       i--;
  2130.       if(j <=COLS-1 && i>=0){
  2131.          if(the_image[i][j] == value)
  2132.             dist6++;
  2133.          else
  2134.             measuring = 0;
  2135.       }
  2136.       else
  2137.          measuring = 0;
  2138.    }  /* ends while measuring */
  2139.    dist6 = ((dist6*14)+7)/10;
  2140.    if(dist6 <= result)
  2141.       result = dist6;
  2142.    if(dist6 < min1){
  2143.       min2 = min1;
  2144.       min1 = dist6;
  2145.    }
  2146.    else
  2147.       if(dist6 < min2)
  2148.          min2 = dist6;
  2149.  
  2150.       /* right and down */
  2151.    measuring = 1;
  2152.    i = a;
  2153.    j = b;
  2154.    while(measuring){
  2155.       j++;
  2156.       i++;
  2157.       if(j <=COLS-1 && i<=ROWS-1){
  2158.          if(the_image[i][j] == value)
  2159.             dist7++;
  2160.          else
  2161.             measuring = 0;
  2162.       }
  2163.       else
  2164.          measuring = 0;
  2165.    }  /* ends while measuring */
  2166.    dist7 = ((dist7*14)+7)/10;
  2167.    if(dist7 <= result)
  2168.       result = dist7;
  2169.    if(dist7 < min1){
  2170.       min2 = min1;
  2171.       min1 = dist7;
  2172.    }
  2173.    else
  2174.       if(dist7 < min2)
  2175.          min2 = dist7;
  2176.  
  2177.       /* left and down */
  2178.    measuring = 1;
  2179.    i = a;
  2180.    j = b;
  2181.    while(measuring){
  2182.       j--;
  2183.       i++;
  2184.       if(j >=0 && i<=ROWS-1){
  2185.          if(the_image[i][j] == value)
  2186.             dist8++;
  2187.          else
  2188.             measuring = 0;
  2189.       }
  2190.       else
  2191.          measuring = 0;
  2192.    }  /* ends while measuring */
  2193.    dist8 = ((dist8*14)+7)/10;
  2194.    if(dist8 <= result)
  2195.       result = dist8;
  2196.    if(dist8 < min1){
  2197.       min2 = min1;
  2198.       min1 = dist8;
  2199.    }
  2200.    else
  2201.       if(dist8 < min2)
  2202.          min2 = dist8;
  2203.  
  2204.    if(min1 == min2)
  2205.       result = value;
  2206.    else
  2207.       result = 0;
  2208.  
  2209.    if(min1 == 0)
  2210.       result = 0;
  2211.  
  2212.    return(result);
  2213. }  /* ends mat_d */
  2214.  
  2215.    /*********************************************
  2216.    *
  2217.    *       file d:\cips\segment.c
  2218.    *
  2219.    *       Functions: This file contains
  2220.    *           adaptive_threshold_segmentation
  2221.    *           append_stack_files
  2222.    *           copy_stack_files
  2223.    *           find_peaks
  2224.    *           find_valley_point
  2225.    *           grow
  2226.    *           insert_into_peaks
  2227.    *           insert_into_deltas
  2228.    *           label_and_check_neighbors
  2229.    *           manual_threshold_segmentation
  2230.    *           peak_threshold_segmentation
  2231.    *           peaks_high_low
  2232.    *           push_data_onto_stack_file
  2233.    *           pop_data_off_of_stack_file
  2234.    *           threshold_image_array
  2235.    *           valley_high_low
  2236.    *           valley_threshold_segmentation
  2237.    *           get_segmentation_options
  2238.    *
  2239.    *       Purpose:
  2240.    *           These functions are part of histogram
  2241.    *           based image segmentation.
  2242.    *
  2243.    *       External Calls:
  2244.    *          wtiff.c - round_off_image_size
  2245.    *                    create_file_if_needed
  2246.    *                    write_array_into_tiff_image
  2247.    *          tiff.c - read_tiff_header
  2248.    *          rtiff.c - read_tiff_image
  2249.    *          numcvrt.c - get_integer
  2250.    *                      get_short
  2251.    *
  2252.    *       Modifications:
  2253.    *           October 1992 - created
  2254.    *
  2255.    ************************************************/
  2256.  
  2257.  
  2258.  
  2259.  
  2260.    /**************************************************
  2261.    *
  2262.    *   manual_threshold_segmentation(...
  2263.    *
  2264.    *   This function segments an image using thresholding
  2265.    *   given the hi and low values of the threshold
  2266.    *   by the calling routine.  It reads in an image
  2267.    *   and writes the result to the output image.
  2268.    *
  2269.    *   If the segment parameter is 0, you only
  2270.    *   threshold the array - you do not segment.
  2271.    *
  2272.    ***************************************************/
  2273.  
  2274. manual_threshold_segmentation(in_name, out_name,
  2275.                               the_image, out_image,
  2276.                               il, ie, ll, le,
  2277.                               hi, low, value, segment)
  2278.    char   in_name[], out_name[];
  2279.    int    il, ie, ll, le, segment;
  2280.    short  hi, low, the_image[ROWS][COLS],
  2281.           out_image[ROWS][COLS], value;
  2282. {
  2283.    int    length, width;
  2284.    struct tiff_header_struct image_header;
  2285.  
  2286.    create_file_if_needed(in_name, out_name, out_image);
  2287.  
  2288.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  2289.    threshold_image_array(the_image, out_image,
  2290.             hi, low, value);
  2291.    if(segment == 1)
  2292.       grow(out_image, value);
  2293.    write_array_into_tiff_image(out_name, out_image,
  2294.                                il, ie, ll, le);
  2295.  
  2296. }  /* ends manual_threshold_segmentation */
  2297.  
  2298.  
  2299.  
  2300.  
  2301.  
  2302.    /************************************************
  2303.    *
  2304.    *   peak_threshold_segmentation(...
  2305.    *
  2306.    *   This function segments an image using
  2307.    *   thresholding.  It uses the histogram peaks
  2308.    *   to find the hi and low values of the
  2309.    *   threshold.
  2310.    *
  2311.    *   If the segment parameter is 0, you only
  2312.    *   threshold the array - you do not segment.
  2313.    *
  2314.    *************************************************/
  2315.  
  2316. peak_threshold_segmentation(in_name, out_name,
  2317.                             the_image, out_image,
  2318.                             il, ie, ll, le,
  2319.                             value, segment)
  2320.    char   in_name[], out_name[];
  2321.    int    il, ie, ll, le, segment;
  2322.    short  the_image[ROWS][COLS],
  2323.           out_image[ROWS][COLS], value;
  2324. {
  2325.    int      length, peak1, peak2, width;
  2326.    short    hi, low;
  2327.    struct   tiff_header_struct image_header;
  2328.    unsigned long histogram[GRAY_LEVELS+1];
  2329.  
  2330.    create_file_if_needed(in_name, out_name, out_image);
  2331.  
  2332.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  2333.    zero_histogram(histogram);
  2334.    calculate_histogram(the_image, histogram);
  2335.    smooth_histogram(histogram);
  2336.    find_peaks(histogram, &peak1, &peak2);
  2337.    peaks_high_low(histogram, peak1, peak2,
  2338.                   &hi, &low);
  2339.    threshold_image_array(the_image, out_image,
  2340.                          hi, low, value);
  2341.    if(segment == 1)
  2342.       grow(out_image, value);
  2343.    write_array_into_tiff_image(out_name, out_image,
  2344.                                il, ie, ll, le);
  2345.  
  2346. }  /* ends peak_threshold_segmentation */
  2347.  
  2348.  
  2349.  
  2350.  
  2351.  
  2352.    /************************************************
  2353.    *
  2354.    *   valley_threshold_segmentation(...
  2355.    *
  2356.    *   This function segments an image using
  2357.    *   thresholding.  It uses the histogram valleys
  2358.    *   to find the hi and low values of the
  2359.    *   threshold.
  2360.    *
  2361.    *   If the segment parameter is 0, you only
  2362.    *   threshold the array - you do not segment.
  2363.    *
  2364.    *************************************************/
  2365.  
  2366. valley_threshold_segmentation(in_name, out_name,
  2367.                               the_image, out_image,
  2368.                               il, ie, ll, le,
  2369.                               value, segment)
  2370.    char   in_name[], out_name[];
  2371.    int    il, ie, ll, le, segment;
  2372.    short  the_image[ROWS][COLS],
  2373.           out_image[ROWS][COLS], value;
  2374. {
  2375.    int      length, peak1, peak2, width;
  2376.    short    hi, low;
  2377.    struct   tiff_header_struct image_header;
  2378.    unsigned long histogram[GRAY_LEVELS+1];
  2379.  
  2380.    create_file_if_needed(in_name, out_name, out_image);
  2381.  
  2382.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  2383.    zero_histogram(histogram);
  2384.    calculate_histogram(the_image, histogram);
  2385.    smooth_histogram(histogram);
  2386.    find_peaks(histogram, &peak1, &peak2);
  2387.    valley_high_low(histogram, peak1, peak2,
  2388.                    &hi, &low);
  2389.    threshold_image_array(the_image, out_image,
  2390.                          hi, low, value);
  2391.    if(segment == 1)
  2392.       grow(out_image, value);
  2393.    write_array_into_tiff_image(out_name, out_image,
  2394.                                il, ie, ll, le);
  2395.  
  2396. }  /* ends valley_threshold_segmentation */
  2397.  
  2398.  
  2399.  
  2400.  
  2401.  
  2402.    /************************************************
  2403.    *
  2404.    *   adaptive_threshold_segmentation(...
  2405.    *
  2406.    *   This function segments an image using
  2407.    *   thresholding.  It uses two passes
  2408.    *   to find the hi and low values of the
  2409.    *   threshold.  The first pass uses the peaks
  2410.    *   of the histogram to find the hi and low
  2411.    *   threshold values.  It thresholds the image
  2412.    *   using these hi lows and calculates the means
  2413.    *   of the object and background.  Then we use
  2414.    *   these means as new peaks to calculate new
  2415.    *   hi and low values.  Finally, we threshold
  2416.    *   the image again using these second hi low
  2417.    *   hi low values.
  2418.    *
  2419.    *   If the segment parameter is 0, you only
  2420.    *   threshold the array - you do not segment.
  2421.    *
  2422.    *************************************************/
  2423.  
  2424. adaptive_threshold_segmentation(in_name, out_name,
  2425.                                 the_image, out_image,
  2426.                                 il, ie, ll, le,
  2427.                                 value, segment)
  2428.    char   in_name[], out_name[];
  2429.    int    il, ie, ll, le, segment;
  2430.    short  the_image[ROWS][COLS],
  2431.           out_image[ROWS][COLS], value;
  2432. {
  2433.    int      length, peak1, peak2, width;
  2434.    short    background, hi, low, object;
  2435.    struct   tiff_header_struct image_header;
  2436.    unsigned long histogram[GRAY_LEVELS+1];
  2437.  
  2438.    create_file_if_needed(in_name, out_name, out_image);
  2439.  
  2440.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  2441.    zero_histogram(histogram);
  2442.    calculate_histogram(the_image, histogram);
  2443.    smooth_histogram(histogram);
  2444.    find_peaks(histogram, &peak1, &peak2);
  2445.    peaks_high_low(histogram, peak1, peak2,
  2446.                   &hi, &low);
  2447.    threshold_and_find_means(the_image, out_image,
  2448.                             hi, low, value,
  2449.                             &object, &background);
  2450.    peaks_high_low(histogram, object, background,
  2451.                   &hi, &low);
  2452.    threshold_image_array(the_image, out_image,
  2453.                          hi, low, value);
  2454.    if(segment == 1)
  2455.       grow(out_image, value);
  2456.    write_array_into_tiff_image(out_name, out_image,
  2457.                                il, ie, ll, le);
  2458.  
  2459. }  /* ends adaptive_threshold_segmentation */
  2460.  
  2461.  
  2462.  
  2463.  
  2464.  
  2465.    /**************************************************
  2466.    *
  2467.    *   threshold_image_array(...
  2468.    *
  2469.    *   This function thresholds an input image array
  2470.    *   and produces a binary output image array.
  2471.    *   If the pixel in the input array is between
  2472.    *   the hi and low values, then it is set to value.
  2473.    *   Otherwise, it is set to 0.
  2474.    *
  2475.    ***************************************************/
  2476.  
  2477.  
  2478. threshold_image_array(in_image, out_image, hi, low, value)
  2479.    short hi, low, in_image[ROWS][COLS],
  2480.          out_image[ROWS][COLS], value;
  2481. {
  2482.    int   counter = 0, i, j;
  2483.    for(i=0; i<ROWS; i++){
  2484.       for(j=0; j<COLS; j++){
  2485.          if(in_image[i][j] >= low  &&
  2486.             in_image[i][j] <= hi){
  2487.             out_image[i][j] = value;
  2488.             counter++;
  2489.          }
  2490.          else
  2491.             out_image[i][j] = 0;
  2492.       }  /* ends loop over j */
  2493.    }  /* ends loop over i */
  2494.    printf("\n\tTIA> set %d points", counter);
  2495. }  /* ends threshold_image_array */
  2496.  
  2497.  
  2498.  
  2499.  
  2500.  
  2501.    /**************************************************
  2502.    *
  2503.    *   threshold_and_find_means(...
  2504.    *
  2505.    *   This function thresholds an input image array
  2506.    *   and produces a binary output image array.
  2507.    *   If the pixel in the input array is between
  2508.    *   the hi and low values, then it is set to value.
  2509.    *   Otherwise, it is set to 0.
  2510.    *
  2511.    ***************************************************/
  2512.  
  2513. threshold_and_find_means(in_image, out_image, hi,
  2514.                          low, value, object_mean,
  2515.                          background_mean)
  2516.    short *background_mean, hi, low,
  2517.          in_image[ROWS][COLS], *object_mean,
  2518.          out_image[ROWS][COLS], value;
  2519. {
  2520.    int      counter = 0,
  2521.             i,
  2522.             j;
  2523.    unsigned long object     = 0,
  2524.                  background = 0;
  2525.  
  2526.    for(i=0; i<ROWS; i++){
  2527.       for(j=0; j<COLS; j++){
  2528.          if(in_image[i][j] >= low  &&
  2529.             in_image[i][j] <= hi){
  2530.             out_image[i][j] = value;
  2531.             counter++;
  2532.             object = object + in_image[i][j];
  2533.          }
  2534.          else{
  2535.             out_image[i][j] = 0;
  2536.             background      = background + in_image[i][j];
  2537.          }
  2538.       }  /* ends loop over j */
  2539.    }  /* ends loop over i */
  2540.    object     = object/counter;
  2541.    background = background/((ROWS*COLS)-counter);
  2542.    *object_mean     = (short)(object);
  2543.    *background_mean = (short)(background);
  2544.    printf("\n\tTAFM> set %d points", counter);
  2545.    printf("\n\tTAFM> object=%d background=%d",
  2546.           *object_mean, *background_mean);
  2547. }  /* ends threshold_and_find_means */
  2548.  
  2549.  
  2550.  
  2551.  
  2552.  
  2553.     /**********************************************
  2554.     *
  2555.     *  grow(...
  2556.     *
  2557.     *  This function is an object detector.
  2558.     *  Its input is an binary image array
  2559.     *  containing 0's and value's.
  2560.     *  It searches through the image and connects
  2561.     *  the adjacent values.
  2562.     *
  2563.     ***********************************************/
  2564.  
  2565. grow(binary, value)
  2566.    short binary[ROWS][COLS],
  2567.          value;
  2568. {
  2569.    char name[80];
  2570.  
  2571.    int first_call,
  2572.        i,
  2573.        j,
  2574.        object_found,
  2575.        pointer,
  2576.        pop_i,
  2577.        pop_j,
  2578.        stack_empty,
  2579.        stack_file_in_use;
  2580.  
  2581.    short g_label, stack[STACK_SIZE][2];
  2582.  
  2583.             /*************************************
  2584.             *
  2585.             *   Now begin the process of growing
  2586.             *   regions.
  2587.             *
  2588.             **************************************/
  2589.  
  2590.    g_label       = 2;
  2591.    object_found  = 0;
  2592.    first_call    = 1;
  2593.  
  2594.    for(i=0; i<ROWS; i++){
  2595.       for(j=0; j<COLS; j++){
  2596.  
  2597.          stack_file_in_use =  0;
  2598.          stack_empty       =  1;
  2599.          pointer           = -1;
  2600.  
  2601.                /**********************************
  2602.                *
  2603.                *  Search for the first pixel of
  2604.                *  a region.
  2605.                *
  2606.                ***********************************/
  2607.  
  2608.          if(binary[i][j] == value){
  2609.             label_and_check_neighbor(binary, stack, 
  2610.                       g_label, &stack_empty, &pointer, 
  2611.                       i, j, value, &stack_file_in_use,
  2612.                       &first_call);
  2613.             object_found = 1;
  2614.          }  /* ends if binary[i]j] == value */
  2615.  
  2616.                /*****************************
  2617.                *
  2618.                *  If the stack is not empty,
  2619.                *  pop the coordinates of
  2620.                *  the pixel off the stack
  2621.                *  and check its 8 neighbors.
  2622.                *
  2623.                *******************************/
  2624.  
  2625.          while(stack_empty == 0){
  2626.             pop_i = stack[pointer][0]; /* POP       */
  2627.             pop_j = stack[pointer][1]; /* OPERATION */
  2628.             --pointer;
  2629.             if(pointer <= 0){
  2630.                if(stack_file_in_use){
  2631.                   pop_data_off_of_stack_file(
  2632.                                  stack,
  2633.                                  &pointer,
  2634.                                  &stack_file_in_use);
  2635.                }  /* ends if stack_file_in_use  */
  2636.                else{
  2637.                   pointer     = 0;
  2638.                   stack_empty = 1;
  2639.                }  /* ends else stack file is
  2640.                      not in use  */
  2641.             }  /*  ends if point <= 0  */
  2642.  
  2643.             label_and_check_neighbor(binary,
  2644.                         stack, g_label,
  2645.                         &stack_empty,
  2646.                         &pointer, pop_i,
  2647.                         pop_j, value,
  2648.                         &stack_file_in_use,
  2649.                         &first_call);
  2650.          }  /* ends while stack_empty == 0 */
  2651.  
  2652.          if(object_found == 1){
  2653.             object_found = 0;
  2654.             ++g_label;
  2655.          }  /* ends if object_found == 1 */
  2656.  
  2657.       }   /* ends loop over j */
  2658.    }  /* ends loop over i */
  2659.  
  2660.    printf("\nGROW> found %d objects", g_label);
  2661.  
  2662. } /* ends grow  */
  2663.  
  2664.  
  2665.  
  2666.  
  2667.  
  2668.    /********************************************
  2669.    *
  2670.    *  label_and_check_neighbors(...
  2671.    *
  2672.    *  This function labels a pixel with an object
  2673.    *  label and then checks the pixel's 8
  2674.    *  neighbors.  If any of the neigbors are
  2675.    *  set, then they are also labeled.
  2676.    *
  2677.    ***********************************************/
  2678.  
  2679. label_and_check_neighbor(binary_image, stack,
  2680.                          g_label, stack_empty,
  2681.                          pointer, r, e, value,
  2682.                          stack_file_in_use,
  2683.                          first_call)
  2684. int   e,
  2685.       *first_call,
  2686.       *pointer,
  2687.       r,
  2688.       *stack_empty,
  2689.       *stack_file_in_use;
  2690.  
  2691. short binary_image[ROWS][COLS],
  2692.       g_label,
  2693.       stack[STACK_SIZE][2],
  2694.       value;
  2695. {
  2696.    int already_labeled = 0,
  2697.        i, j;
  2698.  
  2699.    if (binary_image[r][e] == g_label)
  2700.       already_labeled = 1;
  2701.  
  2702.    binary_image[r][e] = g_label;
  2703.  
  2704.       /***************************************
  2705.       *
  2706.       *   Look at the 8 neighors of the
  2707.       *   point r,e.
  2708.       *
  2709.       *   Ensure the points you are checking
  2710.       *   are in the image, i.e. not less
  2711.       *   than zero and not greater than
  2712.       *   ROWS-1 or COLS-1.
  2713.       *
  2714.       ***************************************/
  2715.  
  2716.    for(i=(r-1); i<=(r+1); i++){
  2717.       for(j=(e-1); j<=(e+1); j++){
  2718.  
  2719.          if((i>=0)   &&
  2720.             (i<=ROWS-1)  &&
  2721.             (j>=0)   &&
  2722.             (j<=COLS-1)){
  2723.  
  2724.             if(binary_image[i][j] == value){
  2725.                *pointer           = *pointer + 1;
  2726.                stack[*pointer][0] = i; /* PUSH      */
  2727.                stack[*pointer][1] = j; /* OPERATION */
  2728.                *stack_empty       = 0;
  2729.  
  2730.                if(*pointer >= (STACK_SIZE -
  2731.                                STACK_FILE_LENGTH)){
  2732.                   push_data_onto_stack_file(stack,
  2733.                             pointer, first_call);
  2734.                   *stack_file_in_use = 1;
  2735.                }  /* ends if *pointer >=
  2736.                      STACK_SIZE - STACK_FILE_LENGTH*/
  2737.  
  2738.             }  /* end of if binary_image == value */
  2739.          }  /* end if i and j are on the image */
  2740.       }  /* ends loop over i rows           */
  2741.    }  /* ends loop over j columns        */
  2742. }  /* ends label_and_check_neighbors  */
  2743.  
  2744.  
  2745.  
  2746.  
  2747.  
  2748.    /****************************************
  2749.    *
  2750.    *   push_data_onto_stack_file(...
  2751.    *
  2752.    *   This function takes the stack array
  2753.    *   and pushes it onto the stack file.
  2754.    *
  2755.    *****************************************/
  2756.  
  2757. push_data_onto_stack_file(stack, pointer, first_call)
  2758.    int   *first_call, *pointer;
  2759.    short stack[STACK_SIZE][2];
  2760. {
  2761.    char  backup_file_name[MAX_NAME_LENGTH];
  2762.    FILE  *backup_file_pointer, *stack_file_pointer;
  2763.    int   diff, i;
  2764.    short holder[STACK_FILE_LENGTH][2];
  2765.  
  2766.    printf("\nSFO> Start of push_data_onto_stack ");
  2767.  
  2768.    diff = STACK_SIZE - STACK_FILE_LENGTH;
  2769.  
  2770.        /*******************************************
  2771.        *
  2772.        *   Copy the elements to be stored to the
  2773.        *   stack file into holder
  2774.        *
  2775.        ********************************************/
  2776.  
  2777.    for(i=0; i<STACK_FILE_LENGTH; i++){
  2778.       holder[i][0] = stack[i][0];
  2779.       holder[i][1] = stack[i][1];
  2780.    }
  2781.  
  2782.        /*******************************************
  2783.        *
  2784.        *   Move the elements of the stack down
  2785.        *
  2786.        *******************************************/
  2787.  
  2788.    for(i=0; i<diff; i++){
  2789.       stack[i][0] = stack[i + STACK_FILE_LENGTH][0];
  2790.       stack[i][1] = stack[i + STACK_FILE_LENGTH][1];
  2791.    }
  2792.  
  2793.        /*******************************************
  2794.        *
  2795.        *   Fill the top of the stack with zeros
  2796.        *
  2797.        *******************************************/
  2798.  
  2799.    for(i=diff; i<STACK_SIZE; i++){
  2800.       stack[i][0] = 0;
  2801.       stack[i][1] = 0;
  2802.    }
  2803.  
  2804.    *pointer = *pointer - STACK_FILE_LENGTH;
  2805.  
  2806.    /************************************************
  2807.    *
  2808.    *   Store the holder array into the stack file.
  2809.    *   Open the stack file for writing in binary
  2810.    *   mode. If the file does not exist it will be
  2811.    *   created. If the file does exist it will be
  2812.    *   over written.
  2813.    *
  2814.    *   PUSH - IF first_time == 1 then write to stack
  2815.    *          ELSE write to stack.bak
  2816.    *          append stack onto stack.bak
  2817.    *          copy stack.bak to stack
  2818.    *          this has the effect of writing
  2819.    *          to the beginning of the stack.
  2820.    *
  2821.    ************************************************/
  2822.  
  2823.    if(*first_call == 1){
  2824.  
  2825.       *first_call = *first_call + 1;
  2826.       if((stack_file_pointer = fopen(STACK_FILE,"wb"))
  2827.                                      == NULL)
  2828.          printf("\nSFO> Could not open stack file");
  2829.       else{
  2830.          /*printf("\n\nSFO> Writing to stack file");*/
  2831.          fwrite(holder, sizeof(holder),
  2832.                 1, stack_file_pointer);
  2833.          fclose(stack_file_pointer);
  2834.       }  /*  ends else could not open stack_file  */
  2835.  
  2836.    }  /*  ends if *first_call == 1  */
  2837.    else{  /* else stack file has been used already  */
  2838.       strcpy(backup_file_name, STACK_FILE);
  2839.       strcat(backup_file_name, ".bak");
  2840.       if((backup_file_pointer =
  2841.           fopen(backup_file_name, "wb")) == NULL)
  2842.          printf("\nSFO> Could not open backup file");
  2843.       else{
  2844.          /*printf("\n\nSFO> Writing to backup file");*/
  2845.          fwrite(holder, sizeof(holder),
  2846.                 1, backup_file_pointer);
  2847.          fclose(backup_file_pointer);
  2848.       }  /*  ends else could not open backup_file  */
  2849.  
  2850.       append_stack_files(backup_file_name,
  2851.                          STACK_FILE, holder);
  2852.       copy_stack_files(backup_file_name,
  2853.                        STACK_FILE, holder);
  2854.  
  2855.    }  /*  ends else first_call != 1  */
  2856.  
  2857.    printf("--- End of push_data_onto_stack");
  2858.  
  2859. }  /* ends push_data_onto_stack_file  */
  2860.  
  2861.  
  2862.  
  2863.  
  2864.  
  2865.    /****************************************
  2866.    *
  2867.    *   pop_data_off_of_stack_file(...
  2868.    *
  2869.    *   This function pops the stack array
  2870.    *   off of the stack file.
  2871.    *
  2872.    *****************************************/
  2873.  
  2874. pop_data_off_of_stack_file(stack, pointer,
  2875.                            stack_file_in_use)
  2876.    int   *pointer, *stack_file_in_use;
  2877.    short stack[STACK_SIZE][2];
  2878. {
  2879.    char  backup_file_name[MAX_NAME_LENGTH];
  2880.    FILE  *backup_file_pointer, *stack_file_pointer;
  2881.    int   i;
  2882.    long  write_counter;
  2883.    short holder[STACK_FILE_LENGTH][2],
  2884.          holder2[STACK_FILE_LENGTH][2];
  2885.  
  2886.        /*******************************************
  2887.        *
  2888.        *   POP - Read 1 time from stack
  2889.        *         Copy the remainder of stack to
  2890.        *            stack.bak
  2891.        *         Copy stack.bak to stack
  2892.        *         This has the effect of popping off
  2893.        *         of the stack.
  2894.        *
  2895.        *   Read the holder array from the stack file.
  2896.        *   Open the stack file for reading in binary
  2897.        *   mode.
  2898.        *
  2899.        *   If it requires more than one write to
  2900.        *   copy the remainder of stack to
  2901.        *   stack.bak then there is still data in the
  2902.        *   stack file so set stack_file_in_use = 1.
  2903.        *   Else set it to 0.
  2904.        *
  2905.        **********************************************/
  2906.  
  2907.    printf("\nSFO> Start of pop_data_off_of_stack ");
  2908.    write_counter = 0;
  2909.  
  2910.    strcpy(backup_file_name, STACK_FILE);
  2911.    strcat(backup_file_name, ".bak");
  2912.  
  2913.    if( (stack_file_pointer =
  2914.           fopen(STACK_FILE, "rb")) == NULL)
  2915.       printf("\nSFO> Could not open stack file");
  2916.    else{
  2917.       /*printf("\n\nSFO> Reading from stack file");*/
  2918.       fread(holder, sizeof(holder),
  2919.             1, stack_file_pointer);
  2920.  
  2921.       backup_file_pointer =
  2922.             fopen(backup_file_name, "wb");
  2923.       while( fread(holder2, sizeof(holder2),
  2924.                    1, stack_file_pointer) ){
  2925.          fwrite(holder2, sizeof(holder2),
  2926.                 1, backup_file_pointer);
  2927.          ++write_counter;
  2928.       }  /* ends while reading  */
  2929.       if(write_counter > 0)
  2930.          *stack_file_in_use = 1;
  2931.       else
  2932.          *stack_file_in_use = 0;
  2933.  
  2934.       fclose(backup_file_pointer);
  2935.       fclose(stack_file_pointer);
  2936.    }  /* ends else could not open stack file  */
  2937.  
  2938.    copy_stack_files(backup_file_name,
  2939.                     STACK_FILE, holder2);
  2940.  
  2941.    for(i=0; i<STACK_FILE_LENGTH; i++){
  2942.       stack[i][0] = holder[i][0];
  2943.       stack[i][1] = holder[i][1];
  2944.    }
  2945.  
  2946.    *pointer = *pointer + STACK_FILE_LENGTH - 1;
  2947.  
  2948.    printf("--- End of pop_data_off_of_stack");
  2949. }  /* ends pop_data_off_of_stack_file  */
  2950.  
  2951.  
  2952.  
  2953.  
  2954.  
  2955.    /*********************************************
  2956.    *
  2957.    *   append_stack_files(...
  2958.    *
  2959.    *   Append the second file onto the end
  2960.    *   of the first.
  2961.    *
  2962.    ***********************************************/
  2963.  
  2964. append_stack_files(first_file, second_file, holder)
  2965.    char first_file[], second_file[];
  2966.    short holder[STACK_FILE_LENGTH][2];
  2967. {
  2968.    FILE  *first, *second;
  2969.    int   i;
  2970.  
  2971.    if((first = fopen(first_file, "r+b")) == NULL)
  2972.       printf("\n\nSFO> Cannot open file %s",
  2973.              first_file);
  2974.  
  2975.    if((second = fopen(second_file, "rb")) == NULL)
  2976.       printf("\n\nSFO> Cannot open file %s",
  2977.              second_file);
  2978.  
  2979.           /*****************************************
  2980.           *
  2981.           *  Seek to the end of the first file and
  2982.           *  to the beginning of the second file.
  2983.           *
  2984.           *******************************************/
  2985.  
  2986.    fseek(first, 0L, 2);
  2987.    fseek(second, 0L, 0);
  2988.  
  2989.    while(fread(holder, sizeof(holder), 1, second) ){
  2990.       fwrite(holder, sizeof(holder), 1, first);
  2991.    }  /* ends while reading  */
  2992.  
  2993.    fclose(first);
  2994.    fclose(second);
  2995.  
  2996. }  /*  ends append_stack_files  */
  2997.  
  2998.  
  2999.  
  3000.  
  3001.  
  3002.    /********************************************
  3003.    *
  3004.    *   copy_stack_files(...
  3005.    *
  3006.    *   Copy the first file to the second.
  3007.    *
  3008.    **********************************************/
  3009.  
  3010. copy_stack_files(first_file, second_file, holder)
  3011.    char first_file[], second_file[];
  3012.    short holder[STACK_FILE_LENGTH][2];
  3013. {
  3014.    FILE  *first, *second;
  3015.    int   i;
  3016.  
  3017.    if( (first = fopen(first_file, "rb")) == NULL)
  3018.       printf("\n\nSFO> Cannot open file %s",
  3019.              first_file);
  3020.  
  3021.    if( (second = fopen(second_file, "wb")) == NULL)
  3022.       printf("\n\nSFO> Cannot open file %s",
  3023.              second_file);
  3024.  
  3025.           /******************************************
  3026.           *
  3027.           *  Seek to the beginning of the first file.
  3028.           *
  3029.           *******************************************/
  3030.  
  3031.    fseek(first, 0L, 0);
  3032.  
  3033.    while( fread(holder, sizeof(holder), 1, first) ){
  3034.       fwrite(holder, sizeof(holder), 1, second);
  3035.    }  /* ends while reading  */
  3036.  
  3037.    fclose(first);
  3038.    fclose(second);
  3039.  
  3040. }  /*  ends copy_stack_files */
  3041.  
  3042.  
  3043.  
  3044.  
  3045.    /********************************************
  3046.    *
  3047.    *   find_peaks(...
  3048.    *
  3049.    *   This function looks through the histogram
  3050.    *   array and finds the two highest peaks.
  3051.    *   The peaks must be separated, cannot be
  3052.    *   next to each other, by a spacing defined
  3053.    *   in cips.h.
  3054.    *
  3055.    *   The peaks array holds the peak value
  3056.    *   in the first place and its location in
  3057.    *   the second place.
  3058.    *
  3059.    *********************************************/
  3060.  
  3061. find_peaks(histogram, peak1, peak2)
  3062.    unsigned long histogram[];
  3063.    int *peak1, *peak2;
  3064. {
  3065.    int distance[PEAKS], peaks[PEAKS][2];
  3066.    int i, j=0, max=0, max_place=0;
  3067.  
  3068.    for(i=0; i<PEAKS; i++){
  3069.       distance[i] =  0;
  3070.       peaks[i][0] = -1;
  3071.       peaks[i][1] = -1;
  3072.    }
  3073.  
  3074.    for(i=0; i<=GRAY_LEVELS; i++){
  3075.       max       = histogram[i];
  3076.       max_place = i;
  3077.       insert_into_peaks(peaks, max, max_place);
  3078.    }  /* ends loop over i */
  3079.  
  3080.    for(i=1; i<PEAKS; i++){
  3081.       distance[i] = peaks[0][1] - peaks[i][1];
  3082.       if(distance[i] < 0)
  3083.          distance[i] = distance[i]*(-1);
  3084.    }
  3085.  
  3086.    *peak1 = peaks[0][1];
  3087.    for(i=PEAKS-1; i>0; i--)
  3088.     if(distance[i] > PEAK_SPACE) *peak2 = peaks[i][1];
  3089.  
  3090. }  /* ends find_peaks */
  3091.  
  3092.  
  3093.  
  3094.  
  3095.  
  3096.    /********************************************
  3097.    *
  3098.    *   insert_into_peaks(...
  3099.    *
  3100.    *   This function takes a value and its
  3101.    *   place in the histogram and inserts them
  3102.    *   into a peaks array.  This helps us rank
  3103.    *   the the peaks in the histogram.
  3104.    *
  3105.    *   The objective is to build a list of
  3106.    *   histogram peaks and thier locations.
  3107.    *
  3108.    *   The peaks array holds the peak value
  3109.    *   in the first place and its location in
  3110.    *   the second place.
  3111.    *
  3112.    *********************************************/
  3113.  
  3114. insert_into_peaks(peaks, max, max_place)
  3115.    int max, max_place, peaks[PEAKS][2];
  3116. {
  3117.    int i, j;
  3118.  
  3119.       /* first case */
  3120.    if(max > peaks[0][0]){
  3121.       for(i=PEAKS-1; i>0; i--){
  3122.          peaks[i][0] = peaks[i-1][0];
  3123.          peaks[i][1] = peaks[i-1][1];
  3124.       }
  3125.       peaks[0][0] = max;
  3126.       peaks[0][1] = max_place;
  3127.    }  /* ends if */
  3128.  
  3129.       /* middle cases */
  3130.    for(j=0; j<PEAKS-3; j++){
  3131.       if(max < peaks[j][0]  && max > peaks[j+1][0]){
  3132.          for(i=PEAKS-1; i>j+1; i--){
  3133.             peaks[i][0] = peaks[i-1][0];
  3134.             peaks[i][1] = peaks[i-1][1];
  3135.          }
  3136.          peaks[j+1][0] = max;
  3137.          peaks[j+1][1] = max_place;
  3138.       }  /* ends if */
  3139.    }  /* ends loop over j */
  3140.       /* last case */
  3141.    if(max < peaks[PEAKS-2][0]  && 
  3142.       max > peaks[PEAKS-1][0]){
  3143.       peaks[PEAKS-1][0] = max;
  3144.       peaks[PEAKS-1][1] = max_place;
  3145.    }  /* ends if */
  3146.  
  3147. }  /* ends insert_into_peaks */
  3148.  
  3149.  
  3150.  
  3151.  
  3152.  
  3153.    /********************************************
  3154.    *
  3155.    *   peaks_high_low(...
  3156.    *
  3157.    *   This function uses the histogram array
  3158.    *   and the peaks to find the best high and
  3159.    *   low threshold values for the threshold
  3160.    *   function.  You want the hi and low values
  3161.    *   so that you will threshold the image around
  3162.    *   the smaller of the two "humps" in the
  3163.    *   histogram.  This is because the smaller
  3164.    *   hump represents the objects while the
  3165.    *   larger hump represents the background.
  3166.    *
  3167.    *********************************************/
  3168.  
  3169. peaks_high_low(histogram, peak1, peak2, hi, low)
  3170.    int  peak1, peak2;
  3171.    short *hi, *low;
  3172.    unsigned long histogram[];
  3173. {
  3174.    int i, mid_point;
  3175.    unsigned long sum1 = 0, sum2 = 0;
  3176.  
  3177.    if(peak1 > peak2)
  3178.       mid_point = ((peak1 - peak2)/2) + peak2;
  3179.    if(peak1 < peak2)
  3180.       mid_point = ((peak2 - peak1)/2) + peak1;
  3181.  
  3182.    for(i=0; i<mid_point; i++)
  3183.       sum1 = sum1 + histogram[i];
  3184.  
  3185.    for(i=mid_point; i<=GRAY_LEVELS; i++)
  3186.       sum2 = sum2 + histogram[i];
  3187.    if(sum1 >= sum2){
  3188.       *low = mid_point;
  3189.       *hi  = GRAY_LEVELS;
  3190.    }
  3191.    else{
  3192.       *low = 0;
  3193.       *hi  = mid_point;
  3194.    }
  3195.  
  3196. }  /* ends peaks_high_low */
  3197.  
  3198.  
  3199.  
  3200.  
  3201.  
  3202.       /********************************************
  3203.       *
  3204.       *   valley_high_low(...
  3205.       *
  3206.       *   This function uses the histogram array
  3207.       *   and the valleys to find the best high and
  3208.       *   low threshold values for the threshold
  3209.       *   function.  You want the hi and low values
  3210.       *   so that you will threshold the image around
  3211.       *   the smaller of the two "humps" in the
  3212.       *   histogram.  This is because the smaller
  3213.       *   hump represents the objects while the
  3214.       *   larger hump represents the background.
  3215.       *
  3216.       *********************************************/
  3217.  
  3218. valley_high_low(histogram, peak1, peak2, hi, low)
  3219.    int  peak1, peak2;
  3220.    short *hi, *low;
  3221.    unsigned long histogram[];
  3222. {
  3223.    int  i, valley_point;
  3224.    unsigned long sum1 = 0, sum2 = 0;
  3225.  
  3226.    find_valley_point(histogram, peak1, peak2,
  3227.                      &valley_point);
  3228.    /*printf("\nVHL> valley point is %d",
  3229.             valley_point);*/
  3230.  
  3231.    for(i=0; i<valley_point; i++)
  3232.       sum1 = sum1 + histogram[i];
  3233.    for(i=valley_point; i<=GRAY_LEVELS; i++)
  3234.       sum2 = sum2 + histogram[i];
  3235.  
  3236.    if(sum1 >= sum2){
  3237.       *low = valley_point;
  3238.       *hi  = GRAY_LEVELS;
  3239.    }
  3240.    else{
  3241.       *low = 0;
  3242.       *hi  = valley_point;
  3243.    }
  3244.  
  3245. }  /* ends valley_high_low */
  3246.  
  3247.  
  3248.  
  3249.  
  3250.  
  3251.    /********************************************
  3252.    *
  3253.    *   find_valley_point(...
  3254.    *
  3255.    *   This function finds the low point of
  3256.    *   the valley between two peaks in a
  3257.    *   histogram.  It starts at the lowest
  3258.    *   peak and works its way up to the
  3259.    *   highest peak.  Along the way, it looks
  3260.    *   at each point in the histogram and inserts
  3261.    *   them into a list of points.  When done,
  3262.    *   it has the location of the smallest histogram
  3263.    *   point - that is the valley point.
  3264.    *
  3265.    *   The deltas array holds the delta value
  3266.    *   in the first place and its location in
  3267.    *   the second place.
  3268.    *
  3269.    *********************************************/
  3270.  
  3271. find_valley_point(histogram, peak1, 
  3272.                   peak2, valley_point)
  3273.    int  peak1, peak2, *valley_point;
  3274.    unsigned long histogram[];
  3275. {
  3276.    int  deltas[PEAKS][2], delta_hist, i;
  3277.  
  3278.    for(i=0; i<PEAKS; i++){
  3279.       deltas[i][0] = 10000;
  3280.       deltas[i][1] =    -1;
  3281.    }
  3282.  
  3283.    if(peak1 < peak2){
  3284.       for(i=peak1+1; i<peak2; i++){
  3285.          delta_hist = (int)(histogram[i]);
  3286.          insert_into_deltas(deltas, delta_hist, i);
  3287.       }  /* ends loop over i */
  3288.    }  /* ends if peak1 < peak2 */
  3289.  
  3290.    if(peak2 < peak1){
  3291.       for(i=peak2+1; i<peak1; i++){
  3292.          delta_hist = (int)(histogram[i]);
  3293.          insert_into_deltas(deltas, delta_hist, i);
  3294.       }  /* ends loop over i */
  3295.    }  /* ends if peak2 < peak1 */
  3296.  
  3297.    *valley_point = deltas[0][1];
  3298.  
  3299. }  /* ends find_valley_point */
  3300.  
  3301.  
  3302.  
  3303.  
  3304.  
  3305.  
  3306.    /********************************************
  3307.    *
  3308.    *   insert_into_deltas(...
  3309.    *
  3310.    *   This function inserts histogram deltas
  3311.    *   into a deltas array.  The smallest delta
  3312.    *   will be at the top of the array.
  3313.    *
  3314.    *   The objective is to build a list of
  3315.    *   histogram area deltas and thier locations.
  3316.    *
  3317.    *   The deltas array holds the delta value
  3318.    *   in the first place and its location in
  3319.    *   the second place.
  3320.    *
  3321.    *********************************************/
  3322.  
  3323. insert_into_deltas(deltas, value, place)
  3324.    int value, place, deltas[PEAKS][2];
  3325. {
  3326.    int i, j;
  3327.  
  3328.       /* first case */
  3329.    if(value < deltas[0][0]){
  3330.       for(i=PEAKS-1; i>0; i--){
  3331.          deltas[i][0] = deltas[i-1][0];
  3332.          deltas[i][1] = deltas[i-1][1];
  3333.       }
  3334.       deltas[0][0] = value;
  3335.       deltas[0][1] = place;
  3336.    }  /* ends if */
  3337.  
  3338.       /* middle cases */
  3339.    for(j=0; j<PEAKS-3; j++){
  3340.       if(value > deltas[j][0]  &&
  3341.          value < deltas[j+1][0]){
  3342.          for(i=PEAKS-1; i>j+1; i--){
  3343.             deltas[i][0] = deltas[i-1][0];
  3344.             deltas[i][1] = deltas[i-1][1];
  3345.          }
  3346.          deltas[j+1][0] = value;
  3347.          deltas[j+1][1] = place;
  3348.       }  /* ends if */
  3349.    }  /* ends loop over j */
  3350.  
  3351.       /* last case */
  3352.    if(value > deltas[PEAKS-2][0]  &&
  3353.       value < deltas[PEAKS-1][0]){
  3354.       deltas[PEAKS-1][0] = value;
  3355.       deltas[PEAKS-1][1] = place;
  3356.    }  /* ends if */
  3357.  
  3358. }  /* ends insert_into_deltas */
  3359.  
  3360.  
  3361.  
  3362.  
  3363.  
  3364.    /********************************************
  3365.    *
  3366.    *   get_segmentation_options(...
  3367.    *
  3368.    *   This function interacts with the user
  3369.    *   to obtain the options for image
  3370.    *   segmentation.
  3371.    *
  3372.    *********************************************/
  3373.  
  3374.  
  3375. get_segmentation_options(method, hi, low, value)
  3376.    char   method[];
  3377.    short  *hi, *low, *value;
  3378. {
  3379.    int   i, not_finished = 1, response;
  3380.  
  3381.    while(not_finished){
  3382.       printf(
  3383.          "\n\nThe image segmentation options are:\n");
  3384.       printf("\n\t1. Method is %s", method);
  3385.       printf("\n\t   (options are manual peaks");
  3386.       printf(        " valleys adapative)");
  3387.       printf("\n\t2. Value is %d", *value);
  3388.       printf("\n\t3. Hi    is %d", *hi);
  3389.       printf("\n\t4. Low   is %d", *low);
  3390.       printf("\n\t   Hi and Low needed only for");
  3391.       printf(        " manual method");
  3392.       printf("\n\nEnter choice (0 = no change):_\b");
  3393.  
  3394.       get_integer(&response);
  3395.  
  3396.       if(response == 0)
  3397.          not_finished = 0;
  3398.  
  3399.       if(response == 1){
  3400.          printf("\nEnter method (options are:");
  3401.          printf(" manual peaks valleys adaptive)\n\t");
  3402.          gets(method);
  3403.       }
  3404.  
  3405.       if(response == 2){
  3406.          printf("\nEnter value: ___\b\b\b");
  3407.          get_short(value);
  3408.       }
  3409.  
  3410.       if(response == 3){
  3411.          printf("\nEnter hi: ___\b\b\b");
  3412.          get_short(hi);
  3413.       }
  3414.       if(response == 4){
  3415.          printf("\nEnter low: ___\b\b\b");
  3416.          get_short(low);
  3417.       }
  3418.  
  3419.    }  /* ends while not_finished */
  3420. }  /* ends get_segmentation_options */
  3421.  
  3422.  
  3423.  
  3424.  
  3425.  
  3426.  
  3427.    /********************************************
  3428.    *
  3429.    *   get_threshold_options(...
  3430.    *
  3431.    *   This function interacts with the user
  3432.    *   to obtain the options for image
  3433.    *   threshold.
  3434.    *
  3435.    *********************************************/
  3436.  
  3437.  
  3438. get_threshold_options(method, hi, low, value)
  3439.    char   method[];
  3440.    short  *hi, *low, *value;
  3441. {
  3442.    int   i, not_finished = 1, response;
  3443.  
  3444.    while(not_finished){
  3445.       printf("\n\nThe image threshold options are:\n");
  3446.       printf("\n\t1. Method is %s", method);
  3447.       printf("\n\t   (options are manual peaks");
  3448.       printf(        " valleys adapative)");
  3449.       printf("\n\t2. Value is %d", *value);
  3450.       printf("\n\t3. Hi    is %d", *hi);
  3451.       printf("\n\t4. Low   is %d", *low);
  3452.       printf("\n\t   Hi and Low needed only for");
  3453.       printf(        " manual method");
  3454.       printf("\n\nEnter choice (0 = no change):_\b");
  3455.  
  3456.       get_integer(&response);
  3457.  
  3458.       if(response == 0)
  3459.          not_finished = 0;
  3460.  
  3461.       if(response == 1){
  3462.          printf("\nEnter method (options are:");
  3463.          printf(" manual peaks valleys adaptive)\n\t");
  3464.          gets(method);
  3465.       }
  3466.  
  3467.       if(response == 2){
  3468.          printf("\nEnter value: ___\b\b\b");
  3469.          get_short(value);
  3470.       }
  3471.  
  3472.       if(response == 3){
  3473.          printf("\nEnter hi: ___\b\b\b");
  3474.          get_short(hi);
  3475.       }
  3476.       if(response == 4){
  3477.          printf("\nEnter low: ___\b\b\b");
  3478.          get_short(low);
  3479.       }
  3480.  
  3481.    }  /* ends while not_finished */
  3482. }  /* ends get_threshold_options */
  3483.  
  3484.  
  3485.  
  3486.        /***********************************************
  3487.        *
  3488.        *       file d:\cips\segment2.c
  3489.        *
  3490.        *       Functions: This file contains
  3491.        *          find_cutoff_point
  3492.        *          edge_region
  3493.        *          gray_shade_region
  3494.        *          edge_gray_shade_region
  3495.        *          pixel_grow
  3496.        *          pixel_label_and_check_neighbors
  3497.        *          is_close
  3498.        *          erode_image_array
  3499.        *          get_edge_region_options
  3500.        *
  3501.        *       Purpose:
  3502.        *          These function implement the three
  3503.        *          segmentation techniques in Image
  3504.        *          Processing part 10.
  3505.        *
  3506.        *       External Calls:
  3507.        *          wtiff.c - round_off_image_size
  3508.        *                    create_file_if_needed
  3509.        *                    write_array_into_tiff_image
  3510.        *          tiff.c - read_tiff_header
  3511.        *          rtiff.c - read_tiff_image
  3512.        *          numcvrt.c - get_integer
  3513.        *          edges.c - quick_edge
  3514.        *                    homogeneity
  3515.        *                    difference_edge
  3516.        *                    contrast_edge
  3517.        *                    gaussian_edge
  3518.        *                    range
  3519.        *                    variance
  3520.        *                    detect_edges
  3521.        *          hist.c - calculate_histogram
  3522.        *                   zero_histogram
  3523.        *          thresh.c - threshold_image_array
  3524.        *
  3525.        *       Modifications:
  3526.        *          5 December 1992 - created
  3527.        *
  3528.        *************************************************/
  3529.  
  3530.  
  3531.  
  3532.  
  3533.      /*******************************************
  3534.      *
  3535.      *   find_cutoff_point(..
  3536.      *
  3537.      *   This function looks at a histogram
  3538.      *   and sets a cuttoff point at a given
  3539.      *   percentage of pixels.
  3540.      *   For example, if percent=0.6, you
  3541.      *   start at 0 in the histogram and count
  3542.      *   up until you've hit 60% of the pixels.
  3543.      *   Then you stop and return that pixel
  3544.      *   value.
  3545.      *
  3546.      ********************************************/
  3547.  
  3548. find_cutoff_point(histogram, percent, cutoff)
  3549.    unsigned long histogram[];
  3550.    float    percent;
  3551.    short    *cutoff;
  3552. {
  3553.    float  fd, fsum, sum_div;
  3554.    int    i, looking;
  3555.    long   lc, lr, num=0, sum=0;
  3556.  
  3557.    sum     = 0;
  3558.    i       = 0;
  3559.    lr      = (long)(ROWS);
  3560.    lc      = (long)(COLS);
  3561.    num     = lr*lc;
  3562.    fd      = (float)(num);
  3563.  
  3564.    while(looking){
  3565.       fsum    = (float)(sum);
  3566.       sum_div = fsum/fd;
  3567.       if(sum_div >= percent)
  3568.          looking = 0;
  3569.       else
  3570.          sum = sum + histogram[i++];
  3571.    }  /* ends while looking */
  3572.  
  3573.    if(i >= 256) i = 255;
  3574.    *cutoff = i;
  3575.    printf("\nCutoff is %d sum=%ld", *cutoff, sum);
  3576. }  /* ends find_cutoff_point */
  3577.  
  3578.  
  3579.  
  3580.  
  3581.  
  3582.      /*******************************************
  3583.      *
  3584.      *   edge_region(..
  3585.      *
  3586.      *   This function segments an image by
  3587.      *   growing regions inside of edges.
  3588.      *   The steps are:
  3589.      *      . detect edges
  3590.      *      . threshold edge output to a
  3591.      *        percent value
  3592.      *      . remove edges from consideration
  3593.      *      . grow regions
  3594.      *
  3595.      *******************************************/
  3596.  
  3597.  
  3598. edge_region(in_name, out_name, the_image, out_image,
  3599.             il, ie, ll, le, edge_type, min_area,
  3600.             max_area, diff, percent, set_value,
  3601.             erode)
  3602.    char     in_name[], out_name[];
  3603.    float    percent;
  3604.    int      edge_type, il, ie, ll, le;
  3605.    short    diff, erode, 
  3606.             max_area, min_area, 
  3607.             set_value,
  3608.             the_image[ROWS][COLS],
  3609.             out_image[ROWS][COLS];
  3610. {
  3611.  
  3612.    int    a, b, count, i, j, k,
  3613.           length, width;
  3614.    short  cutoff;
  3615.    struct tiff_header_struct image_header;
  3616.    unsigned long histogram[GRAY_LEVELS+1];
  3617.  
  3618.  
  3619.    create_file_if_needed(in_name, out_name, out_image);
  3620.  
  3621.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  3622.  
  3623.       /***************************
  3624.       *
  3625.       *   Detect the edges.  Do
  3626.       *   not threshold.
  3627.       *
  3628.       ****************************/
  3629.  
  3630.    if(edge_type == 1  ||
  3631.       edge_type == 2  ||
  3632.       edge_type == 3)
  3633.       detect_edges(in_name, out_name, the_image,
  3634.                    out_image, il, ie, ll, le,
  3635.                    edge_type, 0, 0);
  3636.  
  3637.    if(edge_type == 4){
  3638.       quick_edge(in_name, out_name, the_image,
  3639.                  out_image, il, ie, ll, le,
  3640.                  0, 0);
  3641.    }  /* ends if 4 */
  3642.  
  3643.    if(edge_type == 5){
  3644.       homogeneity(in_name, out_name, the_image,
  3645.                  out_image, il, ie, ll, le,
  3646.                  0, 0);
  3647.    }  /* ends if 5 */
  3648.  
  3649.    if(edge_type == 6){
  3650.       difference_edge(in_name, out_name, the_image,
  3651.                  out_image, il, ie, ll, le,
  3652.                  0, 0);
  3653.    }  /* ends if 6 */
  3654.  
  3655.    if(edge_type == 7){
  3656.       contrast_edge(in_name, out_name, the_image,
  3657.                  out_image, il, ie, ll, le,
  3658.                  0, 0);
  3659.    }  /* ends if 7 */
  3660.  
  3661.    if(edge_type == 8){
  3662.       gaussian_edge(in_name, out_name, the_image,
  3663.                  out_image, il, ie, ll, le,
  3664.                  3, 0, 0);
  3665.    }  /* ends if 8 */
  3666.  
  3667.    if(edge_type == 10){
  3668.       range(in_name, out_name, the_image,
  3669.             out_image, il, ie, ll, le,
  3670.             3, 0, 0);
  3671.    }  /* ends if 10 */
  3672.  
  3673.    if(edge_type == 11){
  3674.       variance(in_name, out_name, the_image,
  3675.                out_image, il, ie, ll, le,
  3676.                0, 0);
  3677.    }  /* ends if 11 */
  3678.  
  3679. /**write_array_into_tiff_image("f:e1.tif", out_image,
  3680. il, ie, ll, le);**/
  3681.  
  3682.       /* copy out_image to the_image */
  3683.    for(i=0; i<ROWS; i++)
  3684.       for(j=0; j<COLS; j++)
  3685.          the_image[i][j] = out_image[i][j];
  3686.  
  3687.       /******************************
  3688.       *
  3689.       *   Threshold the edge detector
  3690.       *   output at a given percent.
  3691.       *   This eliminates the weak
  3692.       *   edges.
  3693.       *
  3694.       *******************************/
  3695.    zero_histogram(histogram);
  3696.    calculate_histogram(the_image, histogram);
  3697.    find_cutoff_point(histogram, percent, &cutoff);
  3698.    threshold_image_array(the_image, out_image,
  3699.                          255, cutoff, set_value);
  3700. /**write_array_into_tiff_image("f:e2.tif", out_image,
  3701. il, ie, ll, le);**/
  3702.  
  3703.    if(erode != 0){
  3704.          /* copy out_image to the_image */
  3705.       for(i=0; i<ROWS; i++)
  3706.          for(j=0; j<COLS; j++)
  3707.             the_image[i][j] = out_image[i][j];
  3708.       erode_image_array(the_image, out_image,
  3709.                         set_value, erode);
  3710.    }  /* ends if erode */
  3711.  
  3712. /**write_array_into_tiff_image("f:e3.tif", out_image,
  3713. il, ie, ll, le);**/
  3714.  
  3715.       /*******************************
  3716.       *
  3717.       *   Set all the edge values to
  3718.       *   FORGET_IT so the region
  3719.       *   growing will not use those
  3720.       *   points.
  3721.       *
  3722.       *******************************/
  3723.  
  3724.    for(i=0; i<ROWS; i++)
  3725.       for(j=0; j<COLS; j++)
  3726.          if(out_image[i][j] == set_value)
  3727.             out_image[i][j] = FORGET_IT;
  3728.  
  3729.    for(i=0; i<ROWS; i++)
  3730.       for(j=0; j<COLS; j++)
  3731.          the_image[i][j] = out_image[i][j];
  3732.  
  3733.    pixel_grow(the_image, out_image, diff,
  3734.               min_area, max_area);
  3735.  
  3736.    write_array_into_tiff_image(out_name, out_image,
  3737.                                il, ie, ll, le);
  3738.  
  3739. }  /* ends edge_region */
  3740.  
  3741.  
  3742.  
  3743.      /*******************************************
  3744.      *
  3745.      *   gray_shade_region(...
  3746.      *
  3747.      *   This function segments an image by
  3748.      *   growing regions based only on gray
  3749.      *   shade.
  3750.      *
  3751.      *******************************************/
  3752.  
  3753.  
  3754. gray_shade_region(in_name, out_name, the_image,
  3755.                   out_image, il, ie, ll, le,
  3756.                   diff, min_area, max_area)
  3757.    char   in_name[], out_name[];
  3758.    int    il, ie, ll, le;
  3759.    short  the_image[ROWS][COLS],
  3760.           out_image[ROWS][COLS],
  3761.           diff, min_area, max_area;
  3762. {
  3763.    int    a, b, big_count, count, i, j, k, l,
  3764.           not_finished, length, width;
  3765.    short  temp[3][3];
  3766.    struct tiff_header_struct image_header;
  3767.  
  3768.    create_file_if_needed(in_name, out_name, out_image);
  3769.  
  3770.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  3771.    pixel_grow(the_image, out_image, diff,
  3772.               min_area, max_area);
  3773.    write_array_into_tiff_image(out_name, out_image,
  3774.                                il, ie, ll, le);
  3775.  
  3776. }  /* ends gray_shade_region */
  3777.  
  3778.  
  3779.  
  3780.  
  3781.  
  3782.      /*******************************************
  3783.      *
  3784.      *   edge_gray_shade_region(..
  3785.      *
  3786.      *   This function segments an image by
  3787.      *   growing gray shade regions inside of
  3788.      *   edges.  It combines the techniques
  3789.      *   of the edge_region and gray_shade_region
  3790.      *   functions.
  3791.      *
  3792.      *   The steps are:
  3793.      *      . detect edges
  3794.      *      . threshold edge output to a
  3795.      *        percent value
  3796.      *      . lay the edges on top of the original
  3797.      *        image to eliminate them from
  3798.      *        consideration
  3799.      *      . grow regions
  3800.      *
  3801.      *******************************************/
  3802.  
  3803. edge_gray_shade_region(in_name, out_name, the_image,
  3804.             out_image, il, ie, ll, le, edge_type,
  3805.             min_area, max_area, diff, percent,
  3806.             set_value, erode)
  3807.    char     in_name[], out_name[];
  3808.    float    percent;
  3809.    int      edge_type, il, ie, ll, le;
  3810.    short    diff, erode, 
  3811.             max_area, min_area, 
  3812.             set_value,
  3813.             the_image[ROWS][COLS],
  3814.             out_image[ROWS][COLS];
  3815. {
  3816.    int    a, b, count, i, j, k,
  3817.           length, width;
  3818.    short  cutoff;
  3819.    struct tiff_header_struct image_header;
  3820.    unsigned long histogram[GRAY_LEVELS+1];
  3821.  
  3822.    create_file_if_needed(in_name, out_name, out_image);
  3823.  
  3824.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  3825.  
  3826.       /***************************
  3827.       *
  3828.       *   Detect the edges.  Do
  3829.       *   not threshold.
  3830.       *
  3831.       ****************************/
  3832.  
  3833.    if(edge_type == 1  ||
  3834.       edge_type == 2  ||
  3835.       edge_type == 3)
  3836.       detect_edges(in_name, out_name, the_image,
  3837.                    out_image, il, ie, ll, le,
  3838.                    edge_type, 0, 0);
  3839.  
  3840.    if(edge_type == 4){
  3841.       quick_edge(in_name, out_name, the_image,
  3842.                  out_image, il, ie, ll, le,
  3843.                  0, 0);
  3844.    }  /* ends if 4 */
  3845.    if(edge_type == 5){
  3846.       homogeneity(in_name, out_name, the_image,
  3847.                  out_image, il, ie, ll, le,
  3848.                  0, 0);
  3849.    }  /* ends if 5 */
  3850.  
  3851.    if(edge_type == 6){
  3852.       difference_edge(in_name, out_name, the_image,
  3853.                  out_image, il, ie, ll, le,
  3854.                  0, 0);
  3855.    }  /* ends if 6 */
  3856.  
  3857.    if(edge_type == 7){
  3858.       contrast_edge(in_name, out_name, the_image,
  3859.                  out_image, il, ie, ll, le,
  3860.                  0, 0);
  3861.    }  /* ends if 7 */
  3862.  
  3863.    if(edge_type == 8){
  3864.       gaussian_edge(in_name, out_name, the_image,
  3865.                  out_image, il, ie, ll, le,
  3866.                  3, 0, 0);
  3867.    }  /* ends if 8 */
  3868.  
  3869.    if(edge_type == 10){
  3870.       range(in_name, out_name, the_image,
  3871.             out_image, il, ie, ll, le,
  3872.             3, 0, 0);
  3873.    }  /* ends if 10 */
  3874.  
  3875.    if(edge_type == 11){
  3876.       variance(in_name, out_name, the_image,
  3877.                out_image, il, ie, ll, le,
  3878.                0, 0);
  3879.    }  /* ends if 11 */
  3880.  
  3881. /**write_array_into_tiff_image("f:e1.tif", out_image,
  3882. il, ie, ll, le);**/
  3883.  
  3884.       /* copy out_image to the_image */
  3885.    for(i=0; i<ROWS; i++)
  3886.       for(j=0; j<COLS; j++)
  3887.          the_image[i][j] = out_image[i][j];
  3888.  
  3889.       /******************************
  3890.       *
  3891.       *   Threshold the edge detector
  3892.       *   output at a given percent.
  3893.       *   This eliminates the weak
  3894.       *   edges.
  3895.       *
  3896.       *******************************/
  3897.  
  3898.    zero_histogram(histogram);
  3899.    calculate_histogram(the_image, histogram);
  3900.    find_cutoff_point(histogram, percent, &cutoff);
  3901.    threshold_image_array(the_image, out_image,
  3902.                          255, cutoff, set_value);
  3903.  
  3904. /**write_array_into_tiff_image("f:e2.tif", out_image,
  3905. il, ie, ll, le);**/
  3906.  
  3907.    if(erode != 0){
  3908.          /* copy out_image to the_image */
  3909.       for(i=0; i<ROWS; i++)
  3910.          for(j=0; j<COLS; j++)
  3911.             the_image[i][j] = out_image[i][j];
  3912.       erode_image_array(the_image, out_image,
  3913.                         set_value, erode);
  3914.    }  /* ends if erode */
  3915.  
  3916. /**write_array_into_tiff_image("f:e3.tif", out_image,
  3917. il, ie, ll, le);**/
  3918.  
  3919.       /*******************************
  3920.       *
  3921.       *   Read the original gray shade
  3922.       *   image back into the_image.
  3923.       *
  3924.       *******************************/
  3925.  
  3926.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  3927.  
  3928.       /*******************************
  3929.       *
  3930.       *   Overlay the edge values
  3931.       *   on top of the original
  3932.       *   image by setting them to
  3933.       *   FORGET_IT so the region
  3934.       *   growing will not use those
  3935.       *   points.
  3936.       *
  3937.       *******************************/
  3938.  
  3939.    for(i=0; i<ROWS; i++)
  3940.       for(j=0; j<COLS; j++)
  3941.          if(out_image[i][j] == set_value)
  3942.             the_image[i][j] = FORGET_IT;
  3943.  
  3944. /**write_array_into_tiff_image("f:e4.tif", the_image,
  3945. il, ie, ll, le);**/
  3946.  
  3947.    pixel_grow(the_image, out_image, diff,
  3948.               min_area, max_area);
  3949.  
  3950.    write_array_into_tiff_image(out_name, out_image,
  3951.                                il, ie, ll, le);
  3952.  
  3953. }  /* ends edge_gray_shade_region */
  3954.  
  3955.  
  3956.  
  3957.  
  3958.     /**********************************************
  3959.     *
  3960.     *   pixel_grow(...
  3961.     *
  3962.     *   The function grows regions.  It is similar
  3963.     *   to the grow function in segment.c, but it
  3964.     *   has several new capabilities.  It can
  3965.     *   eliminate regions if they are too large or
  3966.     *   too small.
  3967.     *
  3968.     *   It ignores pixels = FORGET_IT.  This allows
  3969.     *   it to ignore edges or regions already
  3970.     *   eliminated from consideration.
  3971.     *
  3972.     *   It adds pixels to a growing region only if
  3973.     *   the pixel is close enough to the average gray
  3974.     *   level of that region.
  3975.     *
  3976.     ***********************************************/
  3977.  
  3978. pixel_grow(input, output, diff, min_area, max_area)
  3979.    short input[ROWS][COLS],
  3980.          output[ROWS][COLS],
  3981.          max_area,
  3982.          min_area,
  3983.          diff;
  3984. {
  3985.    char name[80];
  3986.  
  3987.    int count,
  3988.        first_call,
  3989.        i,
  3990.        ii,
  3991.        j,
  3992.        jj,
  3993.        object_found,
  3994.        pointer,
  3995.        pop_i,
  3996.        pop_j,
  3997.        stack_empty,
  3998.        stack_file_in_use;
  3999.  
  4000.    short g_label, target, sum, stack[STACK_SIZE][2];
  4001.  
  4002.    for(i=0; i<ROWS; i++)
  4003.       for(j=0; j<COLS; j++)
  4004.          output[i][j] = 0;
  4005.  
  4006.    g_label       = 2;
  4007.    object_found  = 0;
  4008.    first_call    = 1;
  4009.  
  4010.             /*************************************
  4011.             *
  4012.             *   Now begin the process of growing
  4013.             *   regions.
  4014.             *
  4015.             **************************************/
  4016.  
  4017.    for(i=0; i<ROWS; i++){
  4018. if( (i%4) == 0) printf("\n");
  4019. printf("-i=%3d label=%3d", i, g_label);
  4020.       for(j=0; j<COLS; j++){
  4021.  
  4022.          target            = input[i][j];
  4023.          sum               = target;
  4024.          count             = 0;
  4025.          stack_file_in_use = 0;
  4026.          stack_empty       = 1;
  4027.          pointer           = -1;
  4028.                /**********************************
  4029.                *
  4030.                *  Search for the first pixel of
  4031.                *  a region.  It must not equal
  4032.                *  FORGET_IT, and it must be close
  4033.                *  enough to the target (ave value).
  4034.                *
  4035.                ***********************************/
  4036.  
  4037.          if(input[i][j] != FORGET_IT            &&
  4038.             is_close(input[i][j], target, diff) &&
  4039.             output[i][j] == 0){
  4040.             pixel_label_and_check_neighbor(input,
  4041.                            output, &target, &sum,
  4042.                            &count, stack, g_label,
  4043.                            &stack_empty, &pointer,
  4044.                            i, j, diff,
  4045.                            &stack_file_in_use,
  4046.                            &first_call);
  4047.             object_found = 1;
  4048.          }  /* ends if is_close */
  4049.  
  4050.                /*****************************
  4051.                *
  4052.                *  If the stack is not empty,
  4053.                *  pop the coordinates of
  4054.                *  the pixel off the stack
  4055.                *  and check its 8 neighbors.
  4056.                *
  4057.                *******************************/
  4058.  
  4059.          while(stack_empty == 0){
  4060.             pop_i = stack[pointer][0]; /* POP       */
  4061.             pop_j = stack[pointer][1]; /* OPERATION */
  4062.             --pointer;
  4063.             if(pointer <= 0){
  4064.                if(stack_file_in_use){
  4065.                   pop_data_off_of_stack_file(
  4066.                                  stack,
  4067.                                  &pointer,
  4068.                                  &stack_file_in_use);
  4069.                }  /* ends if stack_file_in_use  */
  4070.                else{
  4071.                   pointer     = 0;
  4072.                   stack_empty = 1;
  4073.                }  /* ends else stack file is
  4074.                      not in use  */
  4075.             }  /*  ends if point <= 0  */
  4076.             pixel_label_and_check_neighbor(input,
  4077.                            output, &target, &sum,
  4078.                            &count, stack, g_label,
  4079.                            &stack_empty, &pointer,
  4080.                            pop_i, pop_j,
  4081.                            diff, &stack_file_in_use,
  4082.                            &first_call);
  4083.          }  /* ends while stack_empty == 0 */
  4084.  
  4085.          if(object_found == 1){
  4086.             object_found = 0;
  4087.  
  4088.                   /**********************************
  4089.                   *
  4090.                   *  The object must be in the
  4091.                   *  size constraints given by
  4092.                   *  min_area and max_area
  4093.                   *
  4094.                   *********************************/
  4095.  
  4096.             if(count >= min_area  &&
  4097.                count <= max_area)
  4098.                ++g_label;
  4099.                   /**********************************
  4100.                   *
  4101.                   *   Remove the object from the
  4102.                   *   output.  Set all pixels in the
  4103.                   *   object you are removing to
  4104.                   *   FORGET_IT.
  4105.                   *
  4106.                   **********************************/
  4107.  
  4108.             else{
  4109.                for(ii=0; ii<ROWS; ii++){
  4110.                   for(jj=0; jj<COLS; jj++){
  4111.                      if(output[ii][jj] == g_label){
  4112.                         output[ii][jj] = 0;
  4113.                         input[ii][jj]  = FORGET_IT;
  4114.                      }  /* ends if output == g_label */
  4115.                   }  /* ends loop over jj */
  4116.                }  /* ends loop over ii */
  4117.             }  /* ends else remove object */
  4118.          }  /* ends if object_found == 1 */
  4119.  
  4120.       }   /* ends loop over j */
  4121.    }  /* ends loop over i */
  4122.  
  4123.    printf("\nGROW> found %d objects", g_label);
  4124.  
  4125. } /* ends pixel_grow  */
  4126.  
  4127.  
  4128.  
  4129.  
  4130.  
  4131.    /********************************************
  4132.    *
  4133.    *  pixel_label_and_check_neighbors(...
  4134.    *
  4135.    *  This function labels a pixel with an object
  4136.    *  label and then checks the pixel's 8
  4137.    *  neighbors.  If any of the neigbors are
  4138.    *  set, then they are also labeled.
  4139.    *
  4140.    *  It also updates the target or ave pixel
  4141.    *  value of the pixels in the region being
  4142.    *  grown.
  4143.    *
  4144.    ***********************************************/
  4145. pixel_label_and_check_neighbor(input_image,
  4146.                          output_image, target,
  4147.                          sum, count, stack,
  4148.                          g_label, stack_empty,
  4149.                          pointer, r, e, diff,
  4150.                          stack_file_in_use,
  4151.                          first_call)
  4152. int   *count,
  4153.       e,
  4154.       *first_call,
  4155.       *pointer,
  4156.       r,
  4157.       *stack_empty,
  4158.       *stack_file_in_use;
  4159.  
  4160. short input_image[ROWS][COLS],
  4161.       output_image[ROWS][COLS],
  4162.       g_label,
  4163.       *sum,
  4164.       *target,
  4165.       stack[STACK_SIZE][2],
  4166.       diff;
  4167. {
  4168.    int already_labeled = 0,
  4169.        i, j;
  4170.  
  4171.    if (output_image[r][e] != 0)
  4172.       already_labeled = 1;
  4173.  
  4174.    output_image[r][e] = g_label;
  4175.    *count  = *count + 1;
  4176.    if(*count > 1){
  4177.       *sum    = *sum + input_image[r][e];
  4178.       *target = *sum / *count;
  4179.    }
  4180.  
  4181.       /***************************************
  4182.       *
  4183.       *   Look at the 8 neighors of the
  4184.       *   point r,e.
  4185.       *
  4186.       *   Ensure the points are close enough
  4187.       *   to the target and do not equal
  4188.       *   FORGET_IT.
  4189.       *
  4190.       *   Ensure the points you are checking
  4191.       *   are in the image, i.e. not less
  4192.       *   than zero and not greater than
  4193.       *   ROWS-1 or COLS-1.
  4194.       *
  4195.       ***************************************/
  4196.  
  4197.    for(i=(r-1); i<=(r+1); i++){
  4198.       for(j=(e-1); j<=(e+1); j++){
  4199.  
  4200.          if((i>=0)   &&
  4201.             (i<=ROWS-1)  &&
  4202.             (j>=0)   &&
  4203.             (j<=COLS-1)){
  4204.  
  4205.             if( input_image[i][j] != FORGET_IT   &&
  4206.                 is_close(input_image[i][j],
  4207.                             *target, diff)       &&
  4208.                 output_image[i][j] == 0){
  4209.                *pointer           = *pointer + 1;
  4210.                stack[*pointer][0] = i; /* PUSH      */
  4211.                stack[*pointer][1] = j; /* OPERATION */
  4212.                *stack_empty       = 0;
  4213.  
  4214.                if(*pointer >= (STACK_SIZE -
  4215.                                STACK_FILE_LENGTH)){
  4216.                   push_data_onto_stack_file(stack,
  4217.                             pointer, first_call);
  4218.                   *stack_file_in_use = 1;
  4219.                }  /* ends if *pointer >=
  4220.                      STACK_SIZE - STACK_FILE_LENGTH*/
  4221.  
  4222.             }  /* ends if is_close */
  4223.          }  /* end if i and j are on the image */
  4224.       }  /* ends loop over i rows           */
  4225.    }  /* ends loop over j columns        */
  4226. }  /* ends pixel_label_and_check_neighbors  */
  4227.  
  4228.  
  4229.  
  4230.    /********************************************
  4231.    *
  4232.    *  is_close(...
  4233.    *
  4234.    *  This function tests to see if two pixel
  4235.    *  values are close enough together.  It
  4236.    *  uses the delta parameter to make this
  4237.    *  judgement.
  4238.    *
  4239.    ***********************************************/
  4240.  
  4241. is_close(a, b, delta)
  4242.    short a, b, delta;
  4243. {
  4244.    int   result = 0;
  4245.    short diff;
  4246.  
  4247.    diff = a-b;
  4248.    if(diff < 0) diff = diff*(-1);
  4249.    if(diff < delta)
  4250.       result = 1;
  4251.    return(result);
  4252. }  /* ends is_close */
  4253.  
  4254.  
  4255.  
  4256.  
  4257.      /*******************************************
  4258.      *
  4259.      *   erode_image_array(..
  4260.      *
  4261.      *   This function erodes pixels.  If a pixel
  4262.      *   equals value and has more than threshold
  4263.      *   neighbors equal to 0, then set that
  4264.      *   pixel in the output to 0.
  4265.      *
  4266.      *******************************************/
  4267.  
  4268.  
  4269. erode_image_array(the_image, out_image,
  4270.                   value, threshold)
  4271.    short  the_image[ROWS][COLS],
  4272.           out_image[ROWS][COLS],
  4273.           threshold,
  4274.           value;
  4275. {
  4276.    int    a, b, count, i, j, k,
  4277.           length, width;
  4278.  
  4279.       /***************************
  4280.       *
  4281.       *   Loop over image array
  4282.       *
  4283.       ****************************/
  4284.  
  4285.    for(i=0; i<ROWS; i++)
  4286.       for(j=0; j<COLS; j++)
  4287.          out_image[i][j] = the_image[i][j];
  4288.  
  4289.    printf("\n");
  4290.  
  4291.    for(i=1; i<ROWS-1; i++){
  4292.       if( (i%10) == 0) printf("%3d", i);
  4293.       for(j=1; j<COLS-1; j++){
  4294.          if(the_image[i][j] == value){
  4295.             count = 0;
  4296.             for(a=-1; a<=1; a++){
  4297.                 for(b=-1; b<=1; b++){
  4298.                       if(the_image[i+a][j+b] == 0)
  4299.                          count++;
  4300.                 }  /*  ends loop over b */
  4301.             }  /* ends loop over a */
  4302.             if(count > threshold) out_image[i][j] = 0;
  4303.          }  /* ends if the_image == value */
  4304.       }  /* ends loop over j */
  4305.    }  /* ends loop over i */
  4306.  
  4307. }  /* ends erode_image_array */
  4308.  
  4309.  
  4310.  
  4311.  
  4312.  
  4313.    /********************************************
  4314.    *
  4315.    *  get_edge_region_options(...
  4316.    *
  4317.    *  This function interacts with the user to   
  4318.    *  get the options needed to call the 
  4319.    *  edge and region based segmentation 
  4320.    *  routines.
  4321.    *
  4322.    ********************************************/
  4323.  
  4324. get_edge_region_options(method, edge_type, 
  4325.          min_area, max_area, set_value, 
  4326.          diff, percent, erode)
  4327.    char  method[];
  4328.    float *percent;
  4329.    int   *edge_type;
  4330.    short *diff, *erode, 
  4331.          *min_area, *max_area, 
  4332.          *set_value;
  4333. {
  4334.    int not_finished = 1, response;
  4335.  
  4336.    while(not_finished){
  4337.       printf("\n\nEdge Region Segmentation Options:");
  4338.       printf("\n\t1.  Method is %s", method);
  4339.       printf("\n\t    Recall: Edge, Gray shade, "
  4340.                       "Combination");
  4341.       printf("\n\t2.  Edge type is %d", *edge_type);
  4342.       printf("\n\t    Recall: ");
  4343.       printf("\n\t     1=Prewitt     2=Kirsch");
  4344.       printf("\n\t     3=Sobel       4=quick");
  4345.       printf("\n\t     5=homogeneity 6=difference");
  4346.       printf("\n\t     7=contrast    8=gaussian");
  4347.       printf("\n\t     10=range      11=variance");
  4348.       printf("\n\t3.  Min area is %d", *min_area);
  4349.       printf("\n\t4.  Max area is %d", *max_area);
  4350.       printf("\n\t5.  Set value is %d", *set_value);
  4351.       printf("\n\t6.  Difference value is %d", *diff);
  4352.       printf("\n\t7.  Threshold percentage is %f",
  4353.                       *percent);
  4354.       printf("\n\t8.  Erode is %d", *erode);
  4355.       printf("\n\nEnter choice (0 = no change) _\b");
  4356.  
  4357.       get_integer(&response);
  4358.  
  4359.       if(response == 0){
  4360.         not_finished = 0;
  4361.       }
  4362.  
  4363.       if(response == 1){
  4364.          printf("\n\t    Recall: Edge, Gray shade, "
  4365.                          "Combination");
  4366.          printf("\n\t> ");
  4367.          gets(method);
  4368.       }
  4369.  
  4370.       if(response == 2){
  4371.          printf("\n\t    Recall:"); 
  4372.          printf("\n\t     1=Prewitt     2=Kirsch");
  4373.          printf("\n\t     3=Sobel       4=quick");
  4374.          printf("\n\t     5=homogeneity 6=difference");
  4375.          printf("\n\t     7=contrast    8=gaussian");
  4376.          printf("\n\t     10=range      11=variance");
  4377.          printf("\n\t__\b");
  4378.          get_integer(edge_type);
  4379.       }
  4380.  
  4381.       if(response == 3){
  4382.          printf("\nEnter min area:__\b\b");
  4383.          get_integer(min_area);
  4384.       }
  4385.  
  4386.       if(response == 4){
  4387.          printf("\nEnter max area:__\b\b");
  4388.          get_integer(max_area);
  4389.       }
  4390.  
  4391.       if(response == 5){
  4392.          printf("\nEnter set value:__\b\b");
  4393.          get_integer(set_value);
  4394.       }
  4395.  
  4396.       if(response == 6){
  4397.          printf("\nEnter difference:__\b\b");
  4398.          get_integer(diff);
  4399.       }
  4400.  
  4401.       if(response == 7){
  4402.          printf("\nEnter threshold percentage:__\b\b");
  4403.          get_float(percent);
  4404.       }
  4405.  
  4406.       if(response == 8){
  4407.          printf("\nEnter erode:__\b\b");
  4408.          get_integer(erode);
  4409.       }
  4410.  
  4411.    }  /* ends while not_finished */
  4412. }  /* ends get_edge_region_options */
  4413.